You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-06 12:20:30 +00:00
Add OpenXR 1.0.22 to thirdparty libraries
Will be compiled and used in the next commit. Co-authored-by: Rémi Verschelde <rverschelde@gmail.com>
This commit is contained in:
committed by
Rémi Verschelde
parent
fcf8c2006d
commit
65bae5a341
@@ -361,12 +361,16 @@ Comment: Multi-channel signed distance field generator
|
|||||||
Copyright: 2016, Viktor Chlumsky
|
Copyright: 2016, Viktor Chlumsky
|
||||||
License: MIT
|
License: MIT
|
||||||
|
|
||||||
|
|
||||||
Files: ./thirdparty/oidn/
|
Files: ./thirdparty/oidn/
|
||||||
Comment: Intel Open Image Denoise
|
Comment: Intel Open Image Denoise
|
||||||
Copyright: 2009-2019, Intel Corporation
|
Copyright: 2009-2019, Intel Corporation
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
|
|
||||||
|
Files: ./thirdparty/openxr/
|
||||||
|
Comment: OpenXR Loader
|
||||||
|
Copyright: 2020-2022, The Khronos Group Inc.
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
Files: ./thirdparty/pcre2/
|
Files: ./thirdparty/pcre2/
|
||||||
Comment: PCRE2
|
Comment: PCRE2
|
||||||
Copyright: 1997-2021, University of Cambridge
|
Copyright: 1997-2021, University of Cambridge
|
||||||
|
|||||||
25
thirdparty/README.md
vendored
25
thirdparty/README.md
vendored
@@ -474,6 +474,7 @@ Files extracted from the upstream source:
|
|||||||
- Files in `core/` folder.
|
- Files in `core/` folder.
|
||||||
- `LICENSE.txt` and `CHANGELOG.md`
|
- `LICENSE.txt` and `CHANGELOG.md`
|
||||||
|
|
||||||
|
|
||||||
## oidn
|
## oidn
|
||||||
|
|
||||||
- Upstream: https://github.com/OpenImageDenoise/oidn
|
- Upstream: https://github.com/OpenImageDenoise/oidn
|
||||||
@@ -505,6 +506,30 @@ Patch files are provided in `oidn/patches/`.
|
|||||||
- scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py)
|
- scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py)
|
||||||
|
|
||||||
|
|
||||||
|
## openxr
|
||||||
|
|
||||||
|
- Upstream: https://github.com/KhronosGroup/OpenXR-SDK
|
||||||
|
- Version: 1.0.22 (458984d7f59d1ae6dc1b597d94b02e4f7132eaba, 2022)
|
||||||
|
- License: Apache 2.0
|
||||||
|
|
||||||
|
Files extracted from upstream source:
|
||||||
|
|
||||||
|
- include/
|
||||||
|
- src/common/
|
||||||
|
- src/loader/
|
||||||
|
- src/*.{c,h}
|
||||||
|
- src/external/jsoncpp/include/
|
||||||
|
- src/external/jsoncpp/src/lib_json/
|
||||||
|
- LICENSE and COPYING.adoc
|
||||||
|
|
||||||
|
Exclude:
|
||||||
|
|
||||||
|
- src/external/android-jni-wrappers and src/external/jnipp (not used yet)
|
||||||
|
- All CMake stuff: cmake/, CMakeLists.txt and *.cmake
|
||||||
|
- All Gradle stuff: *gradle*, AndroidManifest.xml
|
||||||
|
- All following files (and their .license files): *.{def,in,json,map,pom,rc}
|
||||||
|
|
||||||
|
|
||||||
## pcre2
|
## pcre2
|
||||||
|
|
||||||
- Upstream: http://www.pcre.org
|
- Upstream: http://www.pcre.org
|
||||||
|
|||||||
123
thirdparty/openxr/COPYING.adoc
vendored
Normal file
123
thirdparty/openxr/COPYING.adoc
vendored
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
= COPYING.adoc for the Khronos Group OpenXR projects
|
||||||
|
|
||||||
|
// Copyright (c) 2020-2022, The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: CC-BY-4.0
|
||||||
|
|
||||||
|
This document is shared across a number of OpenXR GitHub projects, as the
|
||||||
|
set of files in those projects is partially overlapping.
|
||||||
|
(There is a single "source of truth" internal Khronos GitLab repo these
|
||||||
|
GitHub repositories interact with.)
|
||||||
|
|
||||||
|
== Licenses
|
||||||
|
|
||||||
|
The OpenXR GitHub projects use several licenses.
|
||||||
|
In general, we work to maintain compliance with the
|
||||||
|
https://reuse.software/spec/[REUSE 3.0 specification] with clear copyright
|
||||||
|
holders and license identifier listed for each file, preferably in each
|
||||||
|
file.
|
||||||
|
Where this is not possible, or e.g. when we are using files unmodified from
|
||||||
|
other open-source projects, license data is listed:
|
||||||
|
|
||||||
|
* in an adjacent file of the same name, with the additional extension
|
||||||
|
"`.license`"
|
||||||
|
* in the repository-wide "`.reuse/dep5`" copyright description
|
||||||
|
https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/["DEP5"
|
||||||
|
machine-readable copyright data] file.
|
||||||
|
|
||||||
|
The https://github.com/fsfe/reuse-tool["`reuse`" command line tool] can be
|
||||||
|
used to create a software bill of materials in SPDX format from this data.
|
||||||
|
Note that this tool will typically exclude the generated files, so if the
|
||||||
|
BOM is important to you, you may consider using the
|
||||||
|
https://github.com/KhronosGroup/OpenXR-SDK[OpenXR-SDK] repository that
|
||||||
|
contains the API headers and the loader source with all generated files
|
||||||
|
pre-generated.
|
||||||
|
|
||||||
|
The data in/adjacent to each file is the authoritative license and copyright
|
||||||
|
data.
|
||||||
|
However, for ease of understanding, the following general practices can be
|
||||||
|
observed.
|
||||||
|
(If in doubt, or if the following summary conflicts with the per-file data,
|
||||||
|
the per-file data remains authoritative.)
|
||||||
|
|
||||||
|
* The source files (in asciidoctor and other formats) for the OpenXR
|
||||||
|
Specification, reference pages, and supporting documentation are licensed
|
||||||
|
under the Creative Commons Attribution 4.0 International License (SPDX
|
||||||
|
license identifier "`CC-BY-4.0`").
|
||||||
|
* Header files, scripts, programs, XML files, and other tooling used or
|
||||||
|
generated as part of the build process is licensed under the Apache
|
||||||
|
License, Version 2.0.
|
||||||
|
* For compatibility with external developers working in GPLed projects who
|
||||||
|
have requested it, the main OpenXR headers, XML registry, and loader
|
||||||
|
source are licensed under a dual license with the SPDX license identifier
|
||||||
|
"`Apache-2.0 OR MIT`" .
|
||||||
|
Relevant files include:
|
||||||
|
** "`specification/registry/xr.xml`"
|
||||||
|
** "`include/openxr/openxr_platform_defines.h`"
|
||||||
|
** The generated OpenXR headers "`openxr.h`", "`openxr_platform.h`", and
|
||||||
|
"`openxr_reflection.h`".
|
||||||
|
** Source files in "`src/loader/`", and a few files in "`src/common/`".
|
||||||
|
** Generated source files used by the loader (including pre-generated in
|
||||||
|
OpenXR-SDK): "`common_config.h`", "`xr_generated_loader.cpp`", and
|
||||||
|
"`xr_generated_loader.hpp`".
|
||||||
|
* There are a few files adopted from other open source projects.
|
||||||
|
Such files continue under their original licenses, and appropriately
|
||||||
|
annotated in accordance with REUSE.
|
||||||
|
* Some generated, transient files produced during the course of building the
|
||||||
|
specification, headers, or other targets may not have copyrights.
|
||||||
|
These are typically very short asciidoc fragments describing parts of the
|
||||||
|
OpenXR API, and are incorporated by reference into specification or
|
||||||
|
reference page builds.
|
||||||
|
|
||||||
|
Users outside Khronos who create and post OpenXR Specifications, whether
|
||||||
|
modified or not, should use the CC-BY-4.0 license on the output documents
|
||||||
|
(HTML, PDF, etc.) they generate.
|
||||||
|
|
||||||
|
|
||||||
|
== Frequently Asked Questions
|
||||||
|
|
||||||
|
Q: Why are the HTML and PDF Specifications posted on Khronos' website under
|
||||||
|
a license which is neither CC-BY-4.0 nor Apache 2.0?
|
||||||
|
|
||||||
|
A: The Specifications posted by Khronos in the OpenXR Registry are licensed
|
||||||
|
under the proprietary Khronos Specification License.
|
||||||
|
Only these Specifications are Ratified by the Khronos Board of Promoters,
|
||||||
|
and therefore they are the only Specifications covered by the Khronos
|
||||||
|
Intellectual Property Rights Policy.
|
||||||
|
|
||||||
|
|
||||||
|
Q: Does Khronos allow the creation and distribution of modified versions of
|
||||||
|
the OpenXR Specification, such as translations to other languages?
|
||||||
|
|
||||||
|
A: Yes.
|
||||||
|
Such modified Specifications, since they are not created by Khronos, should
|
||||||
|
be placed under the CC-BY-4.0 license.
|
||||||
|
If you believe your modifications are of general interest, consider
|
||||||
|
contributing them back by making a pull request (PR) on the OpenXR-Docs
|
||||||
|
project.
|
||||||
|
|
||||||
|
|
||||||
|
Q: Can I contribute changes to the OpenXR Specification?
|
||||||
|
|
||||||
|
A: Yes, by opening an Issue or Pull Request (PR) on the
|
||||||
|
link:https://github.com/KhronosGroup/OpenXR-Docs/[OpenXR-Docs] GitHub
|
||||||
|
project.
|
||||||
|
You must execute a click-through Contributor License Agreement, which brings
|
||||||
|
your changes under the umbrella of the Khronos IP policy.
|
||||||
|
|
||||||
|
|
||||||
|
Q: Can you change the license on your files so they're compatible with my
|
||||||
|
license?
|
||||||
|
|
||||||
|
A: We are using a dual license license on `xr.xml`, the main API headers,
|
||||||
|
and the loader source files, to make them compatible with GPL-2.0- and
|
||||||
|
LGPL-2.0/2.1-licensed projects.
|
||||||
|
This replaces earlier approaches of an MIT-like license on the XML and
|
||||||
|
Apache 2.0 on all headers, and allows use of the SPDX license identifier
|
||||||
|
"`Apache-2.0 OR MIT`" to denote the license.
|
||||||
|
|
||||||
|
If you *require* this same compatibility for use of other Apache-2.0
|
||||||
|
licensed files in our repository, please raise an issue identifying the
|
||||||
|
files and we will consider changing those specific files to the dual license
|
||||||
|
as well.
|
||||||
|
|
||||||
202
thirdparty/openxr/LICENSE
vendored
Normal file
202
thirdparty/openxr/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
3925
thirdparty/openxr/include/openxr/openxr.h
vendored
Normal file
3925
thirdparty/openxr/include/openxr/openxr.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
675
thirdparty/openxr/include/openxr/openxr_platform.h
vendored
Normal file
675
thirdparty/openxr/include/openxr/openxr_platform.h
vendored
Normal file
@@ -0,0 +1,675 @@
|
|||||||
|
#ifndef OPENXR_PLATFORM_H_
|
||||||
|
#define OPENXR_PLATFORM_H_ 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This header is generated from the Khronos OpenXR XML API Registry.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "openxr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_thread_settings 1
|
||||||
|
#define XR_KHR_android_thread_settings_SPEC_VERSION 5
|
||||||
|
#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
|
||||||
|
|
||||||
|
typedef enum XrAndroidThreadTypeKHR {
|
||||||
|
XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
|
||||||
|
XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
|
||||||
|
XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
|
||||||
|
XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
|
||||||
|
XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
|
||||||
|
} XrAndroidThreadTypeKHR;
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
|
||||||
|
XrSession session,
|
||||||
|
XrAndroidThreadTypeKHR threadType,
|
||||||
|
uint32_t threadId);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_surface_swapchain 1
|
||||||
|
#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
|
||||||
|
#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
|
||||||
|
XrSession session,
|
||||||
|
const XrSwapchainCreateInfo* info,
|
||||||
|
XrSwapchain* swapchain,
|
||||||
|
jobject* surface);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_android_create_instance 1
|
||||||
|
#define XR_KHR_android_create_instance_SPEC_VERSION 3
|
||||||
|
#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
|
||||||
|
// XrInstanceCreateInfoAndroidKHR extends XrInstanceCreateInfo
|
||||||
|
typedef struct XrInstanceCreateInfoAndroidKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
void* XR_MAY_ALIAS applicationVM;
|
||||||
|
void* XR_MAY_ALIAS applicationActivity;
|
||||||
|
} XrInstanceCreateInfoAndroidKHR;
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_KHR_vulkan_swapchain_format_list 1
|
||||||
|
#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 4
|
||||||
|
#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list"
|
||||||
|
typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t viewFormatCount;
|
||||||
|
const VkFormat* viewFormats;
|
||||||
|
} XrVulkanSwapchainFormatListCreateInfoKHR;
|
||||||
|
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
|
||||||
|
#define XR_KHR_opengl_enable 1
|
||||||
|
#define XR_KHR_opengl_enable_SPEC_VERSION 10
|
||||||
|
#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
// XrGraphicsBindingOpenGLWin32KHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingOpenGLWin32KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
HDC hDC;
|
||||||
|
HGLRC hGLRC;
|
||||||
|
} XrGraphicsBindingOpenGLWin32KHR;
|
||||||
|
#endif // XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XLIB
|
||||||
|
// XrGraphicsBindingOpenGLXlibKHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingOpenGLXlibKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
Display* xDisplay;
|
||||||
|
uint32_t visualid;
|
||||||
|
GLXFBConfig glxFBConfig;
|
||||||
|
GLXDrawable glxDrawable;
|
||||||
|
GLXContext glxContext;
|
||||||
|
} XrGraphicsBindingOpenGLXlibKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_XLIB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
// XrGraphicsBindingOpenGLXcbKHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingOpenGLXcbKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
xcb_connection_t* connection;
|
||||||
|
uint32_t screenNumber;
|
||||||
|
xcb_glx_fbconfig_t fbconfigid;
|
||||||
|
xcb_visualid_t visualid;
|
||||||
|
xcb_glx_drawable_t glxDrawable;
|
||||||
|
xcb_glx_context_t glxContext;
|
||||||
|
} XrGraphicsBindingOpenGLXcbKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||||
|
// XrGraphicsBindingOpenGLWaylandKHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingOpenGLWaylandKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
struct wl_display* display;
|
||||||
|
} XrGraphicsBindingOpenGLWaylandKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_WAYLAND
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageOpenGLKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t image;
|
||||||
|
} XrSwapchainImageOpenGLKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsOpenGLKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsOpenGLKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_OPENGL */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#define XR_KHR_opengl_es_enable 1
|
||||||
|
#define XR_KHR_opengl_es_enable_SPEC_VERSION 8
|
||||||
|
#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
// XrGraphicsBindingOpenGLESAndroidKHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext context;
|
||||||
|
} XrGraphicsBindingOpenGLESAndroidKHR;
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageOpenGLESKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t image;
|
||||||
|
} XrSwapchainImageOpenGLESKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsOpenGLESKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsOpenGLESKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_KHR_vulkan_enable 1
|
||||||
|
#define XR_KHR_vulkan_enable_SPEC_VERSION 8
|
||||||
|
#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
|
||||||
|
// XrGraphicsBindingVulkanKHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
VkInstance instance;
|
||||||
|
VkPhysicalDevice physicalDevice;
|
||||||
|
VkDevice device;
|
||||||
|
uint32_t queueFamilyIndex;
|
||||||
|
uint32_t queueIndex;
|
||||||
|
} XrGraphicsBindingVulkanKHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
VkImage image;
|
||||||
|
} XrSwapchainImageVulkanKHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsVulkanKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
XrVersion minApiVersionSupported;
|
||||||
|
XrVersion maxApiVersionSupported;
|
||||||
|
} XrGraphicsRequirementsVulkanKHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
VkInstance vkInstance,
|
||||||
|
VkPhysicalDevice* vkPhysicalDevice);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||||
|
|
||||||
|
#define XR_KHR_D3D11_enable 1
|
||||||
|
#define XR_KHR_D3D11_enable_SPEC_VERSION 8
|
||||||
|
#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
|
||||||
|
// XrGraphicsBindingD3D11KHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
ID3D11Device* device;
|
||||||
|
} XrGraphicsBindingD3D11KHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
ID3D11Texture2D* texture;
|
||||||
|
} XrSwapchainImageD3D11KHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsD3D11KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
LUID adapterLuid;
|
||||||
|
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||||
|
} XrGraphicsRequirementsD3D11KHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_D3D11 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||||
|
|
||||||
|
#define XR_KHR_D3D12_enable 1
|
||||||
|
#define XR_KHR_D3D12_enable_SPEC_VERSION 8
|
||||||
|
#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
|
||||||
|
// XrGraphicsBindingD3D12KHR extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
ID3D12Device* device;
|
||||||
|
ID3D12CommandQueue* queue;
|
||||||
|
} XrGraphicsBindingD3D12KHR;
|
||||||
|
|
||||||
|
typedef struct XrSwapchainImageD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
ID3D12Resource* texture;
|
||||||
|
} XrSwapchainImageD3D12KHR;
|
||||||
|
|
||||||
|
typedef struct XrGraphicsRequirementsD3D12KHR {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
LUID adapterLuid;
|
||||||
|
D3D_FEATURE_LEVEL minFeatureLevel;
|
||||||
|
} XrGraphicsRequirementsD3D12KHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_D3D12 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#define XR_KHR_win32_convert_performance_counter_time 1
|
||||||
|
#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1
|
||||||
|
#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const LARGE_INTEGER* performanceCounter,
|
||||||
|
XrTime* time);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
LARGE_INTEGER* performanceCounter);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_TIMESPEC
|
||||||
|
|
||||||
|
#define XR_KHR_convert_timespec_time 1
|
||||||
|
#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
|
||||||
|
#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const struct timespec* timespecTime,
|
||||||
|
XrTime* time);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrTime time,
|
||||||
|
struct timespec* timespecTime);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_TIMESPEC */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_KHR_loader_init_android 1
|
||||||
|
#define XR_KHR_loader_init_android_SPEC_VERSION 1
|
||||||
|
#define XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME "XR_KHR_loader_init_android"
|
||||||
|
typedef struct XrLoaderInitInfoAndroidKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
void* XR_MAY_ALIAS applicationVM;
|
||||||
|
void* XR_MAY_ALIAS applicationContext;
|
||||||
|
} XrLoaderInitInfoAndroidKHR;
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_KHR_vulkan_enable2 1
|
||||||
|
#define XR_KHR_vulkan_enable2_SPEC_VERSION 2
|
||||||
|
#define XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME "XR_KHR_vulkan_enable2"
|
||||||
|
typedef XrFlags64 XrVulkanInstanceCreateFlagsKHR;
|
||||||
|
|
||||||
|
// Flag bits for XrVulkanInstanceCreateFlagsKHR
|
||||||
|
|
||||||
|
typedef XrFlags64 XrVulkanDeviceCreateFlagsKHR;
|
||||||
|
|
||||||
|
// Flag bits for XrVulkanDeviceCreateFlagsKHR
|
||||||
|
|
||||||
|
typedef struct XrVulkanInstanceCreateInfoKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
XrSystemId systemId;
|
||||||
|
XrVulkanInstanceCreateFlagsKHR createFlags;
|
||||||
|
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
|
||||||
|
const VkInstanceCreateInfo* vulkanCreateInfo;
|
||||||
|
const VkAllocationCallbacks* vulkanAllocator;
|
||||||
|
} XrVulkanInstanceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef struct XrVulkanDeviceCreateInfoKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
XrSystemId systemId;
|
||||||
|
XrVulkanDeviceCreateFlagsKHR createFlags;
|
||||||
|
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
|
||||||
|
VkPhysicalDevice vulkanPhysicalDevice;
|
||||||
|
const VkDeviceCreateInfo* vulkanCreateInfo;
|
||||||
|
const VkAllocationCallbacks* vulkanAllocator;
|
||||||
|
} XrVulkanDeviceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkan2KHR;
|
||||||
|
|
||||||
|
typedef struct XrVulkanGraphicsDeviceGetInfoKHR {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
XrSystemId systemId;
|
||||||
|
VkInstance vulkanInstance;
|
||||||
|
} XrVulkanGraphicsDeviceGetInfoKHR;
|
||||||
|
|
||||||
|
typedef XrSwapchainImageVulkanKHR XrSwapchainImageVulkan2KHR;
|
||||||
|
|
||||||
|
typedef XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkan2KHR;
|
||||||
|
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanInstanceKHR)(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanDeviceKHR)(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDevice2KHR)(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirements2KHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrVulkanInstanceCreateInfoKHR* createInfo,
|
||||||
|
VkInstance* vulkanInstance,
|
||||||
|
VkResult* vulkanResult);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanDeviceKHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrVulkanDeviceCreateInfoKHR* createInfo,
|
||||||
|
VkDevice* vulkanDevice,
|
||||||
|
VkResult* vulkanResult);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDevice2KHR(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
|
||||||
|
VkPhysicalDevice* vulkanPhysicalDevice);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_EGL
|
||||||
|
|
||||||
|
#define XR_MNDX_egl_enable 1
|
||||||
|
#define XR_MNDX_egl_enable_SPEC_VERSION 1
|
||||||
|
#define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable"
|
||||||
|
// XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo
|
||||||
|
typedef struct XrGraphicsBindingEGLMNDX {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
PFNEGLGETPROCADDRESSPROC getProcAddress;
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext context;
|
||||||
|
} XrGraphicsBindingEGLMNDX;
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_EGL */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#define XR_MSFT_perception_anchor_interop 1
|
||||||
|
#define XR_MSFT_perception_anchor_interop_SPEC_VERSION 1
|
||||||
|
#define XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME "XR_MSFT_perception_anchor_interop"
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT)(XrSession session, IUnknown* perceptionAnchor, XrSpatialAnchorMSFT* anchor);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT)(XrSession session, XrSpatialAnchorMSFT anchor, IUnknown** perceptionAnchor);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPerceptionAnchorMSFT(
|
||||||
|
XrSession session,
|
||||||
|
IUnknown* perceptionAnchor,
|
||||||
|
XrSpatialAnchorMSFT* anchor);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrTryGetPerceptionAnchorFromSpatialAnchorMSFT(
|
||||||
|
XrSession session,
|
||||||
|
XrSpatialAnchorMSFT anchor,
|
||||||
|
IUnknown** perceptionAnchor);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#define XR_MSFT_holographic_window_attachment 1
|
||||||
|
#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1
|
||||||
|
#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment"
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
// XrHolographicWindowAttachmentMSFT extends XrSessionCreateInfo
|
||||||
|
typedef struct XrHolographicWindowAttachmentMSFT {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
IUnknown* holographicSpace;
|
||||||
|
IUnknown* coreWindow;
|
||||||
|
} XrHolographicWindowAttachmentMSFT;
|
||||||
|
#endif // XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_FB_android_surface_swapchain_create 1
|
||||||
|
#define XR_FB_android_surface_swapchain_create_SPEC_VERSION 1
|
||||||
|
#define XR_FB_ANDROID_SURFACE_SWAPCHAIN_CREATE_EXTENSION_NAME "XR_FB_android_surface_swapchain_create"
|
||||||
|
typedef XrFlags64 XrAndroidSurfaceSwapchainFlagsFB;
|
||||||
|
|
||||||
|
// Flag bits for XrAndroidSurfaceSwapchainFlagsFB
|
||||||
|
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB = 0x00000001;
|
||||||
|
static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB = 0x00000002;
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
// XrAndroidSurfaceSwapchainCreateInfoFB extends XrSwapchainCreateInfo
|
||||||
|
typedef struct XrAndroidSurfaceSwapchainCreateInfoFB {
|
||||||
|
XrStructureType type;
|
||||||
|
const void* XR_MAY_ALIAS next;
|
||||||
|
XrAndroidSurfaceSwapchainFlagsFB createFlags;
|
||||||
|
} XrAndroidSurfaceSwapchainCreateInfoFB;
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#define XR_OCULUS_audio_device_guid 1
|
||||||
|
#define XR_OCULUS_audio_device_guid_SPEC_VERSION 1
|
||||||
|
#define XR_OCULUS_AUDIO_DEVICE_GUID_EXTENSION_NAME "XR_OCULUS_audio_device_guid"
|
||||||
|
#define XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS 128
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioOutputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||||
|
typedef XrResult (XRAPI_PTR *PFN_xrGetAudioInputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||||
|
|
||||||
|
#ifndef XR_NO_PROTOTYPES
|
||||||
|
#ifdef XR_EXTENSION_PROTOTYPES
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioOutputDeviceGuidOculus(
|
||||||
|
XrInstance instance,
|
||||||
|
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioInputDeviceGuidOculus(
|
||||||
|
XrInstance instance,
|
||||||
|
wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
|
||||||
|
#endif /* XR_EXTENSION_PROTOTYPES */
|
||||||
|
#endif /* !XR_NO_PROTOTYPES */
|
||||||
|
#endif /* XR_USE_PLATFORM_WIN32 */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_FB_foveation_vulkan 1
|
||||||
|
#define XR_FB_foveation_vulkan_SPEC_VERSION 1
|
||||||
|
#define XR_FB_FOVEATION_VULKAN_EXTENSION_NAME "XR_FB_foveation_vulkan"
|
||||||
|
// XrSwapchainImageFoveationVulkanFB extends XrSwapchainImageVulkanKHR
|
||||||
|
typedef struct XrSwapchainImageFoveationVulkanFB {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
VkImage image;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
} XrSwapchainImageFoveationVulkanFB;
|
||||||
|
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#define XR_FB_swapchain_update_state_android_surface 1
|
||||||
|
#define XR_FB_swapchain_update_state_android_surface_SPEC_VERSION 1
|
||||||
|
#define XR_FB_SWAPCHAIN_UPDATE_STATE_ANDROID_SURFACE_EXTENSION_NAME "XR_FB_swapchain_update_state_android_surface"
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
typedef struct XrSwapchainStateAndroidSurfaceDimensionsFB {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
} XrSwapchainStateAndroidSurfaceDimensionsFB;
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#endif /* XR_USE_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#define XR_FB_swapchain_update_state_opengl_es 1
|
||||||
|
#define XR_FB_swapchain_update_state_opengl_es_SPEC_VERSION 1
|
||||||
|
#define XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME "XR_FB_swapchain_update_state_opengl_es"
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
typedef struct XrSwapchainStateSamplerOpenGLESFB {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
EGLenum minFilter;
|
||||||
|
EGLenum magFilter;
|
||||||
|
EGLenum wrapModeS;
|
||||||
|
EGLenum wrapModeT;
|
||||||
|
EGLenum swizzleRed;
|
||||||
|
EGLenum swizzleGreen;
|
||||||
|
EGLenum swizzleBlue;
|
||||||
|
EGLenum swizzleAlpha;
|
||||||
|
float maxAnisotropy;
|
||||||
|
XrColor4f borderColor;
|
||||||
|
} XrSwapchainStateSamplerOpenGLESFB;
|
||||||
|
#endif // XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#define XR_FB_swapchain_update_state_vulkan 1
|
||||||
|
#define XR_FB_swapchain_update_state_vulkan_SPEC_VERSION 1
|
||||||
|
#define XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME "XR_FB_swapchain_update_state_vulkan"
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
typedef struct XrSwapchainStateSamplerVulkanFB {
|
||||||
|
XrStructureType type;
|
||||||
|
void* XR_MAY_ALIAS next;
|
||||||
|
VkFilter minFilter;
|
||||||
|
VkFilter magFilter;
|
||||||
|
VkSamplerMipmapMode mipmapMode;
|
||||||
|
VkSamplerAddressMode wrapModeS;
|
||||||
|
VkSamplerAddressMode wrapModeT;
|
||||||
|
VkComponentSwizzle swizzleRed;
|
||||||
|
VkComponentSwizzle swizzleGreen;
|
||||||
|
VkComponentSwizzle swizzleBlue;
|
||||||
|
VkComponentSwizzle swizzleAlpha;
|
||||||
|
float maxAnisotropy;
|
||||||
|
XrColor4f borderColor;
|
||||||
|
} XrSwapchainStateSamplerVulkanFB;
|
||||||
|
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#endif /* XR_USE_GRAPHICS_API_VULKAN */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
110
thirdparty/openxr/include/openxr/openxr_platform_defines.h
vendored
Normal file
110
thirdparty/openxr/include/openxr/openxr_platform_defines.h
vendored
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPENXR_PLATFORM_DEFINES_H_
|
||||||
|
#define OPENXR_PLATFORM_DEFINES_H_ 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Platform-specific calling convention macros.
|
||||||
|
*
|
||||||
|
* Platforms should define these so that OpenXR clients call OpenXR functions
|
||||||
|
* with the same calling conventions that the OpenXR implementation expects.
|
||||||
|
*
|
||||||
|
* XRAPI_ATTR - Placed before the return type in function declarations.
|
||||||
|
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
||||||
|
* XRAPI_CALL - Placed after the return type in function declarations.
|
||||||
|
* Useful for MSVC-style calling convention syntax.
|
||||||
|
* XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
||||||
|
*
|
||||||
|
* Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
|
||||||
|
* Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define XRAPI_ATTR
|
||||||
|
// On Windows, functions use the stdcall convention
|
||||||
|
#define XRAPI_CALL __stdcall
|
||||||
|
#define XRAPI_PTR XRAPI_CALL
|
||||||
|
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||||
|
#error "API not supported for the 'armeabi' NDK ABI"
|
||||||
|
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||||
|
// On Android 32-bit ARM targets, functions use the "hardfloat"
|
||||||
|
// calling convention, i.e. float parameters are passed in registers. This
|
||||||
|
// is true even if the rest of the application passes floats on the stack,
|
||||||
|
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
||||||
|
#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||||
|
#define XRAPI_CALL
|
||||||
|
#define XRAPI_PTR XRAPI_ATTR
|
||||||
|
#else
|
||||||
|
// On other platforms, use the default calling convention
|
||||||
|
#define XRAPI_ATTR
|
||||||
|
#define XRAPI_CALL
|
||||||
|
#define XRAPI_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if !defined(XR_NO_STDINT_H)
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||||
|
typedef signed __int8 int8_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef signed __int16 int16_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#endif // !defined( XR_NO_STDINT_H )
|
||||||
|
|
||||||
|
// XR_PTR_SIZE (in bytes)
|
||||||
|
#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
|
||||||
|
#define XR_PTR_SIZE 8
|
||||||
|
#else
|
||||||
|
#define XR_PTR_SIZE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Needed so we can use clang __has_feature portably.
|
||||||
|
#if !defined(XR_COMPILER_HAS_FEATURE)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
|
||||||
|
#else
|
||||||
|
#define XR_COMPILER_HAS_FEATURE(x) 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Identifies if the current compiler has C++11 support enabled.
|
||||||
|
// Does not by itself identify if any given C++11 feature is present.
|
||||||
|
#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
|
||||||
|
#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
|
||||||
|
#define XR_CPP11_ENABLED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Identifies if the current compiler supports C++11 nullptr.
|
||||||
|
#if !defined(XR_CPP_NULLPTR_SUPPORTED)
|
||||||
|
#if defined(XR_CPP11_ENABLED) && \
|
||||||
|
((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
|
||||||
|
(defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
|
||||||
|
(defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||||
|
(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
|
||||||
|
#define XR_CPP_NULLPTR_SUPPORTED 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
2746
thirdparty/openxr/include/openxr/openxr_reflection.h
vendored
Normal file
2746
thirdparty/openxr/include/openxr/openxr_reflection.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
thirdparty/openxr/src/.clang-format
vendored
Normal file
10
thirdparty/openxr/src/.clang-format
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
# Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Use defaults from the Google style with the following exceptions:
|
||||||
|
BasedOnStyle: Google
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 132
|
||||||
|
SortIncludes: false
|
||||||
|
...
|
||||||
47
thirdparty/openxr/src/common/extra_algorithms.h
vendored
Normal file
47
thirdparty/openxr/src/common/extra_algorithms.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Additional functions along the lines of the standard library algorithms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/// Like std::remove_if, except it works on associative containers and it actually removes this.
|
||||||
|
///
|
||||||
|
/// The iterator stuff in here is subtle - .erase() invalidates only that iterator, but it returns a non-invalidated iterator to the
|
||||||
|
/// next valid element which we can use instead of incrementing.
|
||||||
|
template <typename T, typename Pred>
|
||||||
|
static inline void map_erase_if(T &container, Pred &&predicate) {
|
||||||
|
for (auto it = container.begin(); it != container.end();) {
|
||||||
|
if (predicate(*it)) {
|
||||||
|
it = container.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Moves all elements matching the predicate to the end of the vector then erases them.
|
||||||
|
*
|
||||||
|
* Combines the two parts of the erase-remove idiom to simplify things and avoid accidentally using the wrong erase overload.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Alloc, typename Pred>
|
||||||
|
static inline void vector_remove_if_and_erase(std::vector<T, Alloc> &vec, Pred &&predicate) {
|
||||||
|
auto b = vec.begin();
|
||||||
|
auto e = vec.end();
|
||||||
|
vec.erase(std::remove_if(b, e, std::forward<Pred>(predicate)), e);
|
||||||
|
}
|
||||||
322
thirdparty/openxr/src/common/filesystem_utils.cpp
vendored
Normal file
322
thirdparty/openxr/src/common/filesystem_utils.cpp
vendored
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>
|
||||||
|
// Nat Brown <natb@valvesoftware.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "filesystem_utils.hpp"
|
||||||
|
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if defined DISABLE_STD_FILESYSTEM
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include "stdfs_conditions.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_FINAL_FS == 1
|
||||||
|
#include <filesystem>
|
||||||
|
#define FS_PREFIX std::filesystem
|
||||||
|
#elif USE_EXPERIMENTAL_FS == 1
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
#define FS_PREFIX std::experimental::filesystem
|
||||||
|
#elif defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
// Windows fallback includes
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
// Linux/Apple fallback includes
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#define PATH_SEPARATOR ';'
|
||||||
|
#define DIRECTORY_SYMBOL '\\'
|
||||||
|
#define ALTERNATE_DIRECTORY_SYMBOL '/'
|
||||||
|
#else
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (USE_FINAL_FS == 1) || (USE_EXPERIMENTAL_FS == 1)
|
||||||
|
// We can use one of the C++ filesystem packages
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) { return FS_PREFIX::is_regular_file(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) { return FS_PREFIX::is_directory(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) { return FS_PREFIX::exists(path); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
|
||||||
|
FS_PREFIX::path file_path(path);
|
||||||
|
return file_path.is_absolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
FS_PREFIX::path cur_path = FS_PREFIX::current_path();
|
||||||
|
path = cur_path.string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
FS_PREFIX::path path_var(file_path);
|
||||||
|
parent_path = path_var.parent_path().string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
absolute = FS_PREFIX::absolute(path).string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
// std::filesystem::canonical fails on UWP and must be avoided. Further, PathCchCanonicalize is not available on Windows 7 and
|
||||||
|
// PathCanonicalizeW is not available on UWP. However, symbolic links are not important on Windows since the loader uses the
|
||||||
|
// registry for indirection instead, and so this function can be a no-op on Windows.
|
||||||
|
canonical = path;
|
||||||
|
#else
|
||||||
|
canonical = FS_PREFIX::canonical(path).string();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
FS_PREFIX::path parent_path(parent);
|
||||||
|
FS_PREFIX::path child_path(child);
|
||||||
|
FS_PREFIX::path full_path = parent_path / child_path;
|
||||||
|
combined = full_path.string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
for (auto& dir_iter : FS_PREFIX::directory_iterator(path)) {
|
||||||
|
files.push_back(dir_iter.path().filename().string());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
// For pre C++17 compiler that doesn't support experimental filesystem
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) {
|
||||||
|
const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
|
||||||
|
return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) {
|
||||||
|
const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
|
||||||
|
return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) {
|
||||||
|
return (GetFileAttributesW(utf8_to_wide(path).c_str()) != INVALID_FILE_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
|
||||||
|
bool pathStartsWithDir = (path.size() >= 1) && ((path[0] == DIRECTORY_SYMBOL) || (path[0] == ALTERNATE_DIRECTORY_SYMBOL));
|
||||||
|
|
||||||
|
bool pathStartsWithDrive =
|
||||||
|
(path.size() >= 3) && (path[1] == ':' && (path[2] == DIRECTORY_SYMBOL || path[2] == ALTERNATE_DIRECTORY_SYMBOL));
|
||||||
|
|
||||||
|
return pathStartsWithDir || pathStartsWithDrive;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
wchar_t tmp_path[MAX_PATH];
|
||||||
|
if (nullptr != _wgetcwd(tmp_path, MAX_PATH - 1)) {
|
||||||
|
path = wide_to_utf8(tmp_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
std::string full_path;
|
||||||
|
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
|
||||||
|
std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
|
||||||
|
parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
wchar_t tmp_path[MAX_PATH];
|
||||||
|
if (0 != GetFullPathNameW(utf8_to_wide(path).c_str(), MAX_PATH, tmp_path, NULL)) {
|
||||||
|
absolute = wide_to_utf8(tmp_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& absolute) {
|
||||||
|
// PathCchCanonicalize is not available on Windows 7 and PathCanonicalizeW is not available on UWP. However, symbolic links are
|
||||||
|
// not important on Windows since the loader uses the registry for indirection instead, and so this function can be a no-op on
|
||||||
|
// Windows.
|
||||||
|
absolute = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
std::string::size_type parent_len = parent.length();
|
||||||
|
if (0 == parent_len || "." == parent || ".\\" == parent || "./" == parent) {
|
||||||
|
combined = child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char last_char = parent[parent_len - 1];
|
||||||
|
if ((last_char == DIRECTORY_SYMBOL) || (last_char == ALTERNATE_DIRECTORY_SYMBOL)) {
|
||||||
|
parent_len--;
|
||||||
|
}
|
||||||
|
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
std::string searchPath;
|
||||||
|
FileSysUtilsCombinePaths(path, "*", searchPath);
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW file_data;
|
||||||
|
HANDLE file_handle = FindFirstFileW(utf8_to_wide(searchPath).c_str(), &file_data);
|
||||||
|
if (file_handle != INVALID_HANDLE_VALUE) {
|
||||||
|
do {
|
||||||
|
if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
|
files.push_back(wide_to_utf8(file_data.cFileName));
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(file_handle, &file_data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // XR_OS_LINUX/XR_OS_APPLE fallback
|
||||||
|
|
||||||
|
// simple POSIX-compatible implementation of the <filesystem> pieces used by OpenXR
|
||||||
|
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path.c_str(), &path_stat);
|
||||||
|
return S_ISREG(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path.c_str(), &path_stat);
|
||||||
|
return S_ISDIR(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path) { return (access(path.c_str(), F_OK) != -1); }
|
||||||
|
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path) { return (path[0] == DIRECTORY_SYMBOL); }
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path) {
|
||||||
|
char tmp_path[PATH_MAX];
|
||||||
|
if (nullptr != getcwd(tmp_path, PATH_MAX - 1)) {
|
||||||
|
path = tmp_path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
|
||||||
|
std::string full_path;
|
||||||
|
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
|
||||||
|
std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
|
||||||
|
parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
|
||||||
|
// canonical path is absolute
|
||||||
|
return FileSysUtilsGetCanonicalPath(path, absolute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
if (nullptr != realpath(path.c_str(), buf)) {
|
||||||
|
canonical = buf;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
|
||||||
|
std::string::size_type parent_len = parent.length();
|
||||||
|
if (0 == parent_len || "." == parent || "./" == parent) {
|
||||||
|
combined = child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char last_char = parent[parent_len - 1];
|
||||||
|
if (last_char == DIRECTORY_SYMBOL) {
|
||||||
|
parent_len--;
|
||||||
|
}
|
||||||
|
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
|
||||||
|
std::string::size_type start = 0;
|
||||||
|
std::string::size_type location = path_list.find(PATH_SEPARATOR);
|
||||||
|
while (location != std::string::npos) {
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
start = location + 1;
|
||||||
|
location = path_list.find(PATH_SEPARATOR, start);
|
||||||
|
}
|
||||||
|
paths.push_back(path_list.substr(start, location));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
|
||||||
|
DIR* dir = opendir(path.c_str());
|
||||||
|
if (dir == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct dirent* entry;
|
||||||
|
while ((entry = readdir(dir)) != nullptr) {
|
||||||
|
files.emplace_back(entry->d_name);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
46
thirdparty/openxr/src/common/filesystem_utils.hpp
vendored
Normal file
46
thirdparty/openxr/src/common/filesystem_utils.hpp
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Determine if the path indicates a regular file (not a directory or symbolic link)
|
||||||
|
bool FileSysUtilsIsRegularFile(const std::string& path);
|
||||||
|
|
||||||
|
// Determine if the path indicates a directory
|
||||||
|
bool FileSysUtilsIsDirectory(const std::string& path);
|
||||||
|
|
||||||
|
// Determine if the provided path exists on the filesystem
|
||||||
|
bool FileSysUtilsPathExists(const std::string& path);
|
||||||
|
|
||||||
|
// Get the current directory
|
||||||
|
bool FileSysUtilsGetCurrentPath(std::string& path);
|
||||||
|
|
||||||
|
// Get the parent path of a file
|
||||||
|
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path);
|
||||||
|
|
||||||
|
// Determine if the provided path is an absolute path
|
||||||
|
bool FileSysUtilsIsAbsolutePath(const std::string& path);
|
||||||
|
|
||||||
|
// Get the absolute path for a provided file
|
||||||
|
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute);
|
||||||
|
|
||||||
|
// Get the absolute path for a provided file
|
||||||
|
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical);
|
||||||
|
|
||||||
|
// Combine a parent and child directory
|
||||||
|
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined);
|
||||||
|
|
||||||
|
// Parse out individual paths in a path list
|
||||||
|
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths);
|
||||||
|
|
||||||
|
// Record all the filenames for files found in the provided path.
|
||||||
|
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files);
|
||||||
108
thirdparty/openxr/src/common/hex_and_handles.h
vendored
Normal file
108
thirdparty/openxr/src/common/hex_and_handles.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Some utilities, primarily for working with OpenXR handles in a generic way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
inline std::string to_hex(const uint8_t* const data, size_t bytes) {
|
||||||
|
std::string out(2 + bytes * 2, '?');
|
||||||
|
out[0] = '0';
|
||||||
|
out[1] = 'x';
|
||||||
|
static const char* hex = "0123456789abcdef";
|
||||||
|
auto ch = out.end();
|
||||||
|
for (size_t i = 0; i < bytes; ++i) {
|
||||||
|
auto b = data[i];
|
||||||
|
*--ch = hex[(b >> 0) & 0xf];
|
||||||
|
*--ch = hex[(b >> 4) & 0xf];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string to_hex(const T& data) {
|
||||||
|
return to_hex(reinterpret_cast<const uint8_t* const>(&data), sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XR_PTR_SIZE == 8
|
||||||
|
/// Convert a handle into a same-sized integer.
|
||||||
|
template <typename T>
|
||||||
|
static inline uint64_t MakeHandleGeneric(T handle) {
|
||||||
|
return reinterpret_cast<uint64_t>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Treat an integer as a handle
|
||||||
|
template <typename T>
|
||||||
|
static inline T& TreatIntegerAsHandle(uint64_t& handle) {
|
||||||
|
return reinterpret_cast<T&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @overload
|
||||||
|
template <typename T>
|
||||||
|
static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
|
||||||
|
return reinterpret_cast<T const&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does a correctly-sized integer represent a null handle?
|
||||||
|
static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == reinterpret_cast<void*>(handle); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/// Convert a handle into a same-sized integer: no-op on 32-bit systems
|
||||||
|
static inline uint64_t MakeHandleGeneric(uint64_t handle) { return handle; }
|
||||||
|
|
||||||
|
/// Treat an integer as a handle: no-op on 32-bit systems
|
||||||
|
template <typename T>
|
||||||
|
static inline T& TreatIntegerAsHandle(uint64_t& handle) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @overload
|
||||||
|
template <typename T>
|
||||||
|
static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does a correctly-sized integer represent a null handle?
|
||||||
|
static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == handle; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Turns a uint64_t into a string formatted as hex.
|
||||||
|
///
|
||||||
|
/// The core of the HandleToHexString implementation is in here.
|
||||||
|
inline std::string Uint64ToHexString(uint64_t val) { return to_hex(val); }
|
||||||
|
|
||||||
|
/// Turns a uint32_t into a string formatted as hex.
|
||||||
|
inline std::string Uint32ToHexString(uint32_t val) { return to_hex(val); }
|
||||||
|
|
||||||
|
/// Turns an OpenXR handle into a string formatted as hex.
|
||||||
|
template <typename T>
|
||||||
|
inline std::string HandleToHexString(T handle) {
|
||||||
|
return to_hex(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turns a pointer-sized integer into a string formatted as hex.
|
||||||
|
inline std::string UintptrToHexString(uintptr_t val) { return to_hex(val); }
|
||||||
|
|
||||||
|
/// Convert a pointer to a string formatted as hex.
|
||||||
|
template <typename T>
|
||||||
|
inline std::string PointerToHexString(T const* ptr) {
|
||||||
|
return to_hex(ptr);
|
||||||
|
}
|
||||||
114
thirdparty/openxr/src/common/loader_interfaces.h
vendored
Normal file
114
thirdparty/openxr/src/common/loader_interfaces.h
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Forward declare.
|
||||||
|
typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
|
||||||
|
|
||||||
|
// Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance.
|
||||||
|
// This function allows us to pass special API layer information to each layer during the process of creating an Instance.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info,
|
||||||
|
const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance);
|
||||||
|
|
||||||
|
// Loader/API Layer Interface versions
|
||||||
|
// 1 - First version, introduces negotiation structure and functions
|
||||||
|
#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
|
||||||
|
|
||||||
|
// Loader/Runtime Interface versions
|
||||||
|
// 1 - First version, introduces negotiation structure and functions
|
||||||
|
#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
|
||||||
|
|
||||||
|
// Version negotiation values
|
||||||
|
typedef enum XrLoaderInterfaceStructs {
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0,
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_LOADER_INFO,
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST,
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST,
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO,
|
||||||
|
XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO,
|
||||||
|
} XrLoaderInterfaceStructs;
|
||||||
|
|
||||||
|
#define XR_LOADER_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrNegotiateLoaderInfo {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO
|
||||||
|
uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrNegotiateLoaderInfo)
|
||||||
|
uint32_t minInterfaceVersion;
|
||||||
|
uint32_t maxInterfaceVersion;
|
||||||
|
XrVersion minApiVersion;
|
||||||
|
XrVersion maxApiVersion;
|
||||||
|
} XrNegotiateLoaderInfo;
|
||||||
|
|
||||||
|
#define XR_API_LAYER_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrNegotiateApiLayerRequest {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrNegotiateApiLayerRequest)
|
||||||
|
uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION
|
||||||
|
XrVersion layerApiVersion;
|
||||||
|
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
|
||||||
|
PFN_xrCreateApiLayerInstance createApiLayerInstance;
|
||||||
|
} XrNegotiateApiLayerRequest;
|
||||||
|
|
||||||
|
#define XR_RUNTIME_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrNegotiateRuntimeRequest {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST
|
||||||
|
uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrNegotiateRuntimeRequest)
|
||||||
|
uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION
|
||||||
|
XrVersion runtimeApiVersion;
|
||||||
|
PFN_xrGetInstanceProcAddr getInstanceProcAddr;
|
||||||
|
} XrNegotiateRuntimeRequest;
|
||||||
|
|
||||||
|
// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
|
||||||
|
// more API layers needs to expose at least this function.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo,
|
||||||
|
const char *apiLayerName,
|
||||||
|
XrNegotiateApiLayerRequest *apiLayerRequest);
|
||||||
|
|
||||||
|
// Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose
|
||||||
|
// at least this function.
|
||||||
|
typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo,
|
||||||
|
XrNegotiateRuntimeRequest *runtimeRequest);
|
||||||
|
|
||||||
|
// Forward declare.
|
||||||
|
typedef struct XrApiLayerNextInfo XrApiLayerNextInfo;
|
||||||
|
|
||||||
|
#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
|
||||||
|
struct XrApiLayerNextInfo {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrApiLayerNextInfo)
|
||||||
|
char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info
|
||||||
|
PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr
|
||||||
|
PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance
|
||||||
|
XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
|
||||||
|
#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
|
||||||
|
typedef struct XrApiLayerCreateInfo {
|
||||||
|
XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO
|
||||||
|
uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION
|
||||||
|
size_t structSize; // sizeof(XrApiLayerCreateInfo)
|
||||||
|
void *loaderInstance; // Pointer to the LoaderInstance class
|
||||||
|
char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0')
|
||||||
|
XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info
|
||||||
|
} XrApiLayerCreateInfo;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
276
thirdparty/openxr/src/common/object_info.cpp
vendored
Normal file
276
thirdparty/openxr/src/common/object_info.cpp
vendored
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>
|
||||||
|
// Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
// Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "object_info.h"
|
||||||
|
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
std::string XrSdkLogObjectInfo::ToString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << Uint64ToHexString(handle);
|
||||||
|
if (!name.empty()) {
|
||||||
|
oss << " (" << name << ")";
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectInfoCollection::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
|
||||||
|
// If name is empty, we should erase it
|
||||||
|
if (object_name.empty()) {
|
||||||
|
RemoveObject(object_handle, object_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, add it or update the name
|
||||||
|
XrSdkLogObjectInfo new_obj = {object_handle, object_type};
|
||||||
|
|
||||||
|
// If it already exists, update the name
|
||||||
|
auto lookup_info = LookUpStoredObjectInfo(new_obj);
|
||||||
|
if (lookup_info != nullptr) {
|
||||||
|
lookup_info->name = object_name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It doesn't exist, so add a new info block
|
||||||
|
new_obj.name = object_name;
|
||||||
|
object_info_.push_back(new_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectInfoCollection::RemoveObject(uint64_t object_handle, XrObjectType object_type) {
|
||||||
|
vector_remove_if_and_erase(
|
||||||
|
object_info_, [=](XrSdkLogObjectInfo const& info) { return info.handle == object_handle && info.type == object_type; });
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkLogObjectInfo const* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const {
|
||||||
|
auto e = object_info_.end();
|
||||||
|
auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });
|
||||||
|
if (it != e) {
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkLogObjectInfo* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) {
|
||||||
|
auto e = object_info_.end();
|
||||||
|
auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });
|
||||||
|
if (it != e) {
|
||||||
|
return &(*it);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectInfoCollection::LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const {
|
||||||
|
auto info_lookup = LookUpStoredObjectInfo(info.objectHandle, info.objectType);
|
||||||
|
if (info_lookup != nullptr) {
|
||||||
|
info.objectName = info_lookup->name.c_str();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectInfoCollection::LookUpObjectName(XrSdkLogObjectInfo& info) const {
|
||||||
|
auto info_lookup = LookUpStoredObjectInfo(info);
|
||||||
|
if (info_lookup != nullptr) {
|
||||||
|
info.name = info_lookup->name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<XrDebugUtilsObjectNameInfoEXT> PopulateObjectNameInfo(std::vector<XrSdkLogObjectInfo> const& obj) {
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> ret;
|
||||||
|
ret.reserve(obj.size());
|
||||||
|
std::transform(obj.begin(), obj.end(), std::back_inserter(ret), [](XrSdkLogObjectInfo const& info) {
|
||||||
|
return XrDebugUtilsObjectNameInfoEXT{XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, nullptr, info.type, info.handle,
|
||||||
|
info.name.c_str()};
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamesAndLabels::NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab)
|
||||||
|
: sdk_objects(std::move(obj)), objects(PopulateObjectNameInfo(sdk_objects)), labels(std::move(lab)) {}
|
||||||
|
|
||||||
|
void NamesAndLabels::PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& callback_data) const {
|
||||||
|
callback_data.objects = objects.empty() ? nullptr : const_cast<XrDebugUtilsObjectNameInfoEXT*>(objects.data());
|
||||||
|
callback_data.objectCount = static_cast<uint32_t>(objects.size());
|
||||||
|
callback_data.sessionLabels = labels.empty() ? nullptr : const_cast<XrDebugUtilsLabelEXT*>(labels.data());
|
||||||
|
callback_data.sessionLabelCount = static_cast<uint32_t>(labels.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const {
|
||||||
|
auto session_label_iterator = session_labels_.find(session);
|
||||||
|
if (session_label_iterator != session_labels_.end()) {
|
||||||
|
auto& XrSdkSessionLabels = *session_label_iterator->second;
|
||||||
|
// Copy the debug utils labels in reverse order in the the labels vector.
|
||||||
|
std::transform(XrSdkSessionLabels.rbegin(), XrSdkSessionLabels.rend(), std::back_inserter(labels),
|
||||||
|
[](XrSdkSessionLabelPtr const& label) { return label->debug_utils_label; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkSessionLabel::XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual)
|
||||||
|
: label_name(label_info.labelName), debug_utils_label(label_info), is_individual_label(individual) {
|
||||||
|
// Update the c string pointer to the one we hold.
|
||||||
|
debug_utils_label.labelName = label_name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkSessionLabelPtr XrSdkSessionLabel::make(const XrDebugUtilsLabelEXT& label_info, bool individual) {
|
||||||
|
XrSdkSessionLabelPtr ret(new XrSdkSessionLabel(label_info, individual));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void DebugUtilsData::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
|
||||||
|
object_info_.AddObjectName(object_handle, object_type, object_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always want to remove the old individual label before we do anything else.
|
||||||
|
// So, do that in it's own method
|
||||||
|
void DebugUtilsData::RemoveIndividualLabel(XrSdkSessionLabelList& label_vec) {
|
||||||
|
if (!label_vec.empty() && label_vec.back()->is_individual_label) {
|
||||||
|
label_vec.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkSessionLabelList* DebugUtilsData::GetSessionLabelList(XrSession session) {
|
||||||
|
auto session_label_iterator = session_labels_.find(session);
|
||||||
|
if (session_label_iterator == session_labels_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return session_label_iterator->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkSessionLabelList& DebugUtilsData::GetOrCreateSessionLabelList(XrSession session) {
|
||||||
|
XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr == nullptr) {
|
||||||
|
std::unique_ptr<XrSdkSessionLabelList> vec(new XrSdkSessionLabelList);
|
||||||
|
vec_ptr = vec.get();
|
||||||
|
session_labels_[session] = std::move(vec);
|
||||||
|
}
|
||||||
|
return *vec_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info) {
|
||||||
|
auto& vec = GetOrCreateSessionLabelList(session);
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition into a new label region
|
||||||
|
RemoveIndividualLabel(vec);
|
||||||
|
|
||||||
|
// Start the new label region
|
||||||
|
vec.emplace_back(XrSdkSessionLabel::make(label_info, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::EndLabelRegion(XrSession session) {
|
||||||
|
XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Individual labels do not stay around in the transition out of label region
|
||||||
|
RemoveIndividualLabel(*vec_ptr);
|
||||||
|
|
||||||
|
// Remove the last label region
|
||||||
|
if (!vec_ptr->empty()) {
|
||||||
|
vec_ptr->pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info) {
|
||||||
|
auto& vec = GetOrCreateSessionLabelList(session);
|
||||||
|
|
||||||
|
// Remove any individual layer that might already be there
|
||||||
|
RemoveIndividualLabel(vec);
|
||||||
|
|
||||||
|
// Insert a new individual label
|
||||||
|
vec.emplace_back(XrSdkSessionLabel::make(label_info, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::DeleteObject(uint64_t object_handle, XrObjectType object_type) {
|
||||||
|
object_info_.RemoveObject(object_handle, object_type);
|
||||||
|
|
||||||
|
if (object_type == XR_OBJECT_TYPE_SESSION) {
|
||||||
|
auto session = TreatIntegerAsHandle<XrSession>(object_handle);
|
||||||
|
XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
|
||||||
|
if (vec_ptr != nullptr) {
|
||||||
|
session_labels_.erase(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::DeleteSessionLabels(XrSession session) { session_labels_.erase(session); }
|
||||||
|
|
||||||
|
NamesAndLabels DebugUtilsData::PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const {
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> labels;
|
||||||
|
for (auto& obj : objects) {
|
||||||
|
// Check for any names that have been associated with the objects and set them up here
|
||||||
|
object_info_.LookUpObjectName(obj);
|
||||||
|
// If this is a session, see if there are any labels associated with it for us to add
|
||||||
|
// to the callback content.
|
||||||
|
if (XR_OBJECT_TYPE_SESSION == obj.type) {
|
||||||
|
LookUpSessionLabels(obj.GetTypedHandle<XrSession>(), labels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {objects, labels};
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugUtilsData::WrapCallbackData(AugmentedCallbackData* aug_data,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) const {
|
||||||
|
// If there's nothing to add, just return the original data as the augmented copy
|
||||||
|
aug_data->exported_data = callback_data;
|
||||||
|
if (object_info_.Empty() || callback_data->objectCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspect each of the callback objects
|
||||||
|
bool name_found = false;
|
||||||
|
for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
|
||||||
|
auto& current_obj = callback_data->objects[obj];
|
||||||
|
name_found |= (nullptr != object_info_.LookUpStoredObjectInfo(current_obj.objectHandle, current_obj.objectType));
|
||||||
|
|
||||||
|
// If this is a session, record any labels associated with it
|
||||||
|
if (XR_OBJECT_TYPE_SESSION == current_obj.objectType) {
|
||||||
|
XrSession session = TreatIntegerAsHandle<XrSession>(current_obj.objectHandle);
|
||||||
|
LookUpSessionLabels(session, aug_data->labels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we found nothing to add, return the original data
|
||||||
|
if (!name_found && aug_data->labels.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found additional data - modify an internal copy and return that as the exported data
|
||||||
|
memcpy(&aug_data->modified_data, callback_data, sizeof(XrDebugUtilsMessengerCallbackDataEXT));
|
||||||
|
aug_data->new_objects.assign(callback_data->objects, callback_data->objects + callback_data->objectCount);
|
||||||
|
|
||||||
|
// Record (overwrite) the names of all incoming objects provided in our internal list
|
||||||
|
for (auto& obj : aug_data->new_objects) {
|
||||||
|
object_info_.LookUpObjectName(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update local copy & point export to it
|
||||||
|
aug_data->modified_data.objects = aug_data->new_objects.data();
|
||||||
|
aug_data->modified_data.sessionLabelCount = static_cast<uint32_t>(aug_data->labels.size());
|
||||||
|
aug_data->modified_data.sessionLabels = aug_data->labels.empty() ? nullptr : aug_data->labels.data();
|
||||||
|
aug_data->exported_data = &aug_data->modified_data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
229
thirdparty/openxr/src/common/object_info.h
vendored
Normal file
229
thirdparty/openxr/src/common/object_info.h
vendored
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// Copyright (c) 2019 Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>, Ryan Pavlik <ryan.pavlik@collabora.com
|
||||||
|
//
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* The core of an XR_EXT_debug_utils implementation, used/shared by the loader and several SDK layers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct XrSdkGenericObject {
|
||||||
|
//! Type-erased handle value
|
||||||
|
uint64_t handle;
|
||||||
|
|
||||||
|
//! Kind of object this handle refers to
|
||||||
|
XrObjectType type;
|
||||||
|
/// Un-erase the type of the handle and get it properly typed again.
|
||||||
|
///
|
||||||
|
/// Note: Does not check the type before doing it!
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType& GetTypedHandle() {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @overload
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType const& GetTypedHandle() const {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Create from a typed handle and object type
|
||||||
|
template <typename T>
|
||||||
|
XrSdkGenericObject(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
|
||||||
|
|
||||||
|
//! Create from an untyped handle value (integer) and object type
|
||||||
|
XrSdkGenericObject(uint64_t h, XrObjectType t) : handle(h), type(t) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XrSdkLogObjectInfo {
|
||||||
|
//! Type-erased handle value
|
||||||
|
uint64_t handle;
|
||||||
|
|
||||||
|
//! Kind of object this handle refers to
|
||||||
|
XrObjectType type;
|
||||||
|
|
||||||
|
//! To be assigned by the application - not part of this object's identity
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
/// Un-erase the type of the handle and get it properly typed again.
|
||||||
|
///
|
||||||
|
/// Note: Does not check the type before doing it!
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType& GetTypedHandle() {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @overload
|
||||||
|
template <typename HandleType>
|
||||||
|
HandleType const& GetTypedHandle() const {
|
||||||
|
return TreatIntegerAsHandle<HandleType&>(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSdkLogObjectInfo() = default;
|
||||||
|
|
||||||
|
//! Create from a typed handle and object type
|
||||||
|
template <typename T>
|
||||||
|
XrSdkLogObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
|
||||||
|
|
||||||
|
//! Create from an untyped handle value (integer) and object type
|
||||||
|
XrSdkLogObjectInfo(uint64_t h, XrObjectType t) : handle(h), type(t) {}
|
||||||
|
//! Create from an untyped handle value (integer), object type, and name
|
||||||
|
XrSdkLogObjectInfo(uint64_t h, XrObjectType t, const char* n) : handle(h), type(t), name(n == nullptr ? "" : n) {}
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! True if the two object infos have the same handle value and handle type
|
||||||
|
static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrSdkLogObjectInfo const& b) {
|
||||||
|
return a.handle == b.handle && a.type == b.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @overload
|
||||||
|
static inline bool Equivalent(XrDebugUtilsObjectNameInfoEXT const& a, XrSdkLogObjectInfo const& b) {
|
||||||
|
return a.objectHandle == b.handle && a.objectType == b.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @overload
|
||||||
|
static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrDebugUtilsObjectNameInfoEXT const& b) { return Equivalent(b, a); }
|
||||||
|
|
||||||
|
/// Object info registered with calls to xrSetDebugUtilsObjectNameEXT
|
||||||
|
class ObjectInfoCollection {
|
||||||
|
public:
|
||||||
|
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
|
||||||
|
|
||||||
|
void RemoveObject(uint64_t object_handle, XrObjectType object_type);
|
||||||
|
|
||||||
|
//! Find the stored object info, if any, matching handle and type.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrSdkLogObjectInfo const* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const;
|
||||||
|
|
||||||
|
//! Find the stored object info, if any, matching handle and type.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrSdkLogObjectInfo* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info);
|
||||||
|
|
||||||
|
//! Find the stored object info, if any.
|
||||||
|
//! Return nullptr if not found.
|
||||||
|
XrSdkLogObjectInfo const* LookUpStoredObjectInfo(uint64_t handle, XrObjectType type) const {
|
||||||
|
return LookUpStoredObjectInfo({handle, type});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Find the object name, if any, and update debug utils info accordingly.
|
||||||
|
//! Return true if found and updated.
|
||||||
|
bool LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const;
|
||||||
|
|
||||||
|
//! Find the object name, if any, and update logging info accordingly.
|
||||||
|
//! Return true if found and updated.
|
||||||
|
bool LookUpObjectName(XrSdkLogObjectInfo& info) const;
|
||||||
|
|
||||||
|
//! Is the collection empty?
|
||||||
|
bool Empty() const { return object_info_.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Object names that have been set for given objects
|
||||||
|
std::vector<XrSdkLogObjectInfo> object_info_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XrSdkSessionLabel;
|
||||||
|
using XrSdkSessionLabelPtr = std::unique_ptr<XrSdkSessionLabel>;
|
||||||
|
using XrSdkSessionLabelList = std::vector<XrSdkSessionLabelPtr>;
|
||||||
|
|
||||||
|
struct XrSdkSessionLabel {
|
||||||
|
static XrSdkSessionLabelPtr make(const XrDebugUtilsLabelEXT& label_info, bool individual);
|
||||||
|
|
||||||
|
std::string label_name;
|
||||||
|
XrDebugUtilsLabelEXT debug_utils_label;
|
||||||
|
bool is_individual_label;
|
||||||
|
|
||||||
|
private:
|
||||||
|
XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The metadata for a collection of objects. Must persist unmodified during the entire debug messenger call!
|
||||||
|
struct NamesAndLabels {
|
||||||
|
NamesAndLabels() = default;
|
||||||
|
NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab);
|
||||||
|
/// C++ structure owning the data (strings) backing the objects vector.
|
||||||
|
std::vector<XrSdkLogObjectInfo> sdk_objects;
|
||||||
|
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> objects;
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> labels;
|
||||||
|
|
||||||
|
/// Populate the debug utils callback data structure.
|
||||||
|
void PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& data) const;
|
||||||
|
// XrDebugUtilsMessengerCallbackDataEXT MakeCallbackData() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AugmentedCallbackData {
|
||||||
|
std::vector<XrDebugUtilsLabelEXT> labels;
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> new_objects;
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT modified_data;
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* exported_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Tracks all the data (handle names and session labels) required to fully augment XR_EXT_debug_utils-related calls.
|
||||||
|
class DebugUtilsData {
|
||||||
|
public:
|
||||||
|
DebugUtilsData() = default;
|
||||||
|
|
||||||
|
DebugUtilsData(const DebugUtilsData&) = delete;
|
||||||
|
DebugUtilsData& operator=(const DebugUtilsData&) = delete;
|
||||||
|
|
||||||
|
bool Empty() const { return object_info_.Empty() && session_labels_.empty(); }
|
||||||
|
|
||||||
|
//! Core of implementation for xrSetDebugUtilsObjectNameEXT
|
||||||
|
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
|
||||||
|
|
||||||
|
/// Core of implementation for xrSessionBeginDebugUtilsLabelRegionEXT
|
||||||
|
void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info);
|
||||||
|
|
||||||
|
/// Core of implementation for xrSessionEndDebugUtilsLabelRegionEXT
|
||||||
|
void EndLabelRegion(XrSession session);
|
||||||
|
|
||||||
|
/// Core of implementation for xrSessionInsertDebugUtilsLabelEXT
|
||||||
|
void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info);
|
||||||
|
|
||||||
|
/// Removes all labels associated with a session - call in xrDestroySession and xrDestroyInstance (for all child sessions)
|
||||||
|
void DeleteSessionLabels(XrSession session);
|
||||||
|
|
||||||
|
/// Retrieve labels for the given session, if any, and push them in reverse order on the vector.
|
||||||
|
void LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const;
|
||||||
|
|
||||||
|
/// Removes all data related to this object - including session labels if it's a session.
|
||||||
|
///
|
||||||
|
/// Does not take care of handling child objects - you must do this yourself.
|
||||||
|
void DeleteObject(uint64_t object_handle, XrObjectType object_type);
|
||||||
|
|
||||||
|
/// Given the collection of objects, populate their names and list of labels
|
||||||
|
NamesAndLabels PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const;
|
||||||
|
|
||||||
|
void WrapCallbackData(AugmentedCallbackData* aug_data,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* provided_callback_data) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RemoveIndividualLabel(XrSdkSessionLabelList& label_vec);
|
||||||
|
XrSdkSessionLabelList* GetSessionLabelList(XrSession session);
|
||||||
|
XrSdkSessionLabelList& GetOrCreateSessionLabelList(XrSession session);
|
||||||
|
|
||||||
|
// Session labels: one vector of them per session.
|
||||||
|
std::unordered_map<XrSession, std::unique_ptr<XrSdkSessionLabelList>> session_labels_;
|
||||||
|
|
||||||
|
// Names for objects.
|
||||||
|
ObjectInfoCollection object_info_;
|
||||||
|
};
|
||||||
345
thirdparty/openxr/src/common/platform_utils.hpp
vendored
Normal file
345
thirdparty/openxr/src/common/platform_utils.hpp
vendored
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// OpenXR paths and registry key locations
|
||||||
|
#define OPENXR_RELATIVE_PATH "openxr/"
|
||||||
|
#define OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/implicit.d"
|
||||||
|
#define OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/explicit.d"
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
#define OPENXR_REGISTRY_LOCATION "SOFTWARE\\Khronos\\OpenXR\\"
|
||||||
|
#define OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Implicit"
|
||||||
|
#define OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Explicit"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// OpenXR Loader environment variables of interest
|
||||||
|
#define OPENXR_RUNTIME_JSON_ENV_VAR "XR_RUNTIME_JSON"
|
||||||
|
#define OPENXR_API_LAYER_PATH_ENV_VAR "XR_API_LAYER_PATH"
|
||||||
|
|
||||||
|
// This is a CMake generated file with #defines for any functions/includes
|
||||||
|
// that it found present and build-time configuration.
|
||||||
|
// If you don't have this file, on non-Windows you'll need to define
|
||||||
|
// one of HAVE_SECURE_GETENV or HAVE___SECURE_GETENV depending on which
|
||||||
|
// of secure_getenv or __secure_getenv are present
|
||||||
|
#ifdef OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
#include "common_config.h"
|
||||||
|
#endif // OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
|
||||||
|
// Environment variables
|
||||||
|
#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
static inline char* ImplGetEnv(const char* name) { return getenv(name); }
|
||||||
|
|
||||||
|
static inline int ImplSetEnv(const char* name, const char* value, int overwrite) { return setenv(name, value, overwrite); }
|
||||||
|
|
||||||
|
static inline char* ImplGetSecureEnv(const char* name) {
|
||||||
|
#ifdef HAVE_SECURE_GETENV
|
||||||
|
return secure_getenv(name);
|
||||||
|
#elif defined(HAVE___SECURE_GETENV)
|
||||||
|
return __secure_getenv(name);
|
||||||
|
#else
|
||||||
|
#pragma message( \
|
||||||
|
"Warning: Falling back to non-secure getenv for environmental" \
|
||||||
|
"lookups! Consider updating to a different libc.")
|
||||||
|
|
||||||
|
return ImplGetEnv(name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#endif // defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
|
||||||
|
#if defined(XR_OS_LINUX)
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetEnv(const char* name) {
|
||||||
|
auto str = detail::ImplGetEnv(name);
|
||||||
|
if (str == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
|
||||||
|
auto str = detail::ImplGetSecureEnv(name);
|
||||||
|
if (str == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsGetEnvSet(const char* name) { return detail::ImplGetEnv(name) != nullptr; }
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
|
||||||
|
const int shouldOverwrite = 1;
|
||||||
|
int result = detail::ImplSetEnv(name, value, shouldOverwrite);
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_APPLE)
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetEnv(const char* name) {
|
||||||
|
auto str = detail::ImplGetEnv(name);
|
||||||
|
if (str == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
|
||||||
|
auto str = detail::ImplGetSecureEnv(name);
|
||||||
|
if (str == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsGetEnvSet(const char* name) { return detail::ImplGetEnv(name) != nullptr; }
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
|
||||||
|
const int shouldOverwrite = 1;
|
||||||
|
int result = detail::ImplSetEnv(name, value, shouldOverwrite);
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefix for the Apple global runtime JSON file name
|
||||||
|
static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
|
||||||
|
static const std::string rt_filename = "/active_runtime.json";
|
||||||
|
|
||||||
|
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
|
||||||
|
file_name = rt_dir_prefix;
|
||||||
|
file_name += std::to_string(major_version);
|
||||||
|
file_name += rt_filename;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
inline void LogError(const std::string& error) { OutputDebugStringA(error.c_str()); }
|
||||||
|
#else
|
||||||
|
#define LogError(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline std::wstring utf8_to_wide(const std::string& utf8Text) {
|
||||||
|
if (utf8Text.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring wideText;
|
||||||
|
const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
|
||||||
|
if (wideLength == 0) {
|
||||||
|
LogError("utf8_to_wide get size error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiByteToWideChar returns number of chars of the input buffer, regardless of null terminitor
|
||||||
|
wideText.resize(wideLength, 0);
|
||||||
|
wchar_t* wideString = const_cast<wchar_t*>(wideText.data()); // mutable data() only exists in c++17
|
||||||
|
const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength);
|
||||||
|
if (length != wideLength) {
|
||||||
|
LogError("utf8_to_wide convert string error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return wideText;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string wide_to_utf8(const std::wstring& wideText) {
|
||||||
|
if (wideText.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string narrowText;
|
||||||
|
int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
|
||||||
|
if (narrowLength == 0) {
|
||||||
|
LogError("wide_to_utf8 get size error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// WideCharToMultiByte returns number of chars of the input buffer, regardless of null terminitor
|
||||||
|
narrowText.resize(narrowLength, 0);
|
||||||
|
char* narrowString = const_cast<char*>(narrowText.data()); // mutable data() only exists in c++17
|
||||||
|
const int length =
|
||||||
|
::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr);
|
||||||
|
if (length != narrowLength) {
|
||||||
|
LogError("wide_to_utf8 convert string error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return narrowText;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the current process has an integrity level > SECURITY_MANDATORY_MEDIUM_RID.
|
||||||
|
static inline bool IsHighIntegrityLevel() {
|
||||||
|
// Execute this check once and save the value as a static bool.
|
||||||
|
static bool isHighIntegrityLevel = ([] {
|
||||||
|
HANDLE processToken;
|
||||||
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &processToken)) {
|
||||||
|
// Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
|
||||||
|
uint8_t mandatoryLabelBuffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)]{};
|
||||||
|
DWORD bufferSize;
|
||||||
|
if (GetTokenInformation(processToken, TokenIntegrityLevel, mandatoryLabelBuffer, sizeof(mandatoryLabelBuffer),
|
||||||
|
&bufferSize) != 0) {
|
||||||
|
const auto mandatoryLabel = reinterpret_cast<const TOKEN_MANDATORY_LABEL*>(mandatoryLabelBuffer);
|
||||||
|
if (mandatoryLabel->Label.Sid != 0) {
|
||||||
|
const DWORD subAuthorityCount = *GetSidSubAuthorityCount(mandatoryLabel->Label.Sid);
|
||||||
|
const DWORD integrityLevel = *GetSidSubAuthority(mandatoryLabel->Label.Sid, subAuthorityCount - 1);
|
||||||
|
CloseHandle(processToken);
|
||||||
|
return integrityLevel > SECURITY_MANDATORY_MEDIUM_RID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(processToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return isHighIntegrityLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given environment variable exists.
|
||||||
|
// The name is a case-sensitive UTF8 string.
|
||||||
|
static inline bool PlatformUtilsGetEnvSet(const char* name) {
|
||||||
|
const std::wstring wname = utf8_to_wide(name);
|
||||||
|
const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
|
||||||
|
// GetEnvironmentVariable returns 0 when environment variable does not exist or there is an error.
|
||||||
|
return 0 != valSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the environment variable value for the given name.
|
||||||
|
// Returns an empty string if the environment variable doesn't exist or if it exists but is empty.
|
||||||
|
// Use PlatformUtilsGetEnvSet to tell if it exists.
|
||||||
|
// The name is a case-sensitive UTF8 string.
|
||||||
|
static inline std::string PlatformUtilsGetEnv(const char* name) {
|
||||||
|
const std::wstring wname = utf8_to_wide(name);
|
||||||
|
const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
|
||||||
|
// GetEnvironmentVariable returns 0 when environment variable does not exist or there is an error.
|
||||||
|
// The size includes the null-terminator, so a size of 1 is means the variable was explicitly set to empty.
|
||||||
|
if (valSize == 0 || valSize == 1) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnvironmentVariable returns size including null terminator for "query size" call.
|
||||||
|
std::wstring wValue(valSize, 0);
|
||||||
|
wchar_t* wValueData = &wValue[0];
|
||||||
|
|
||||||
|
// GetEnvironmentVariable returns string length, excluding null terminator for "get value"
|
||||||
|
// call if there was enough capacity. Else it returns the required capacity (including null terminator).
|
||||||
|
const DWORD length = ::GetEnvironmentVariableW(wname.c_str(), wValueData, (DWORD)wValue.size());
|
||||||
|
if ((length == 0) || (length >= wValue.size())) { // If error or the variable increased length between calls...
|
||||||
|
LogError("GetEnvironmentVariable get value error: " + std::to_string(::GetLastError()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
wValue.resize(length); // Strip the null terminator.
|
||||||
|
|
||||||
|
return wide_to_utf8(wValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acts the same as PlatformUtilsGetEnv except returns an empty string if IsHighIntegrityLevel.
|
||||||
|
static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
|
||||||
|
// Do not allow high integrity processes to act on data that can be controlled by medium integrity processes.
|
||||||
|
if (IsHighIntegrityLevel()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// No secure version for Windows so the above integrity check is needed.
|
||||||
|
return PlatformUtilsGetEnv(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets an environment variable via UTF8 strings.
|
||||||
|
// The name is case-sensitive.
|
||||||
|
// Overwrites the variable if it already exists.
|
||||||
|
// Returns true if it could be set.
|
||||||
|
static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
|
||||||
|
const std::wstring wname = utf8_to_wide(name);
|
||||||
|
const std::wstring wvalue = utf8_to_wide(value);
|
||||||
|
BOOL result = ::SetEnvironmentVariableW(wname.c_str(), wvalue.c_str());
|
||||||
|
return (result != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_ANDROID)
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsGetEnvSet(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetEnv(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetSecureEnv(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsSetEnv(const char* /* name */, const char* /* value */) {
|
||||||
|
// Stub func
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
// Intended to be only used as a fallback on Android, with a more open, "native" technique used in most cases
|
||||||
|
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
|
||||||
|
// Prefix for the runtime JSON file name
|
||||||
|
static const char* rt_dir_prefixes[] = {"/oem", "/vendor", "/system"};
|
||||||
|
static const std::string rt_filename = "/active_runtime.json";
|
||||||
|
static const std::string subdir = "/etc/openxr/";
|
||||||
|
for (const auto prefix : rt_dir_prefixes) {
|
||||||
|
auto path = prefix + subdir + std::to_string(major_version) + rt_filename;
|
||||||
|
struct stat buf;
|
||||||
|
if (0 == stat(path.c_str(), &buf)) {
|
||||||
|
file_name = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else // Not Linux, Apple, nor Windows
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsGetEnvSet(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetEnv(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string PlatformUtilsGetSecureEnv(const char* /* name */) {
|
||||||
|
// Stub func
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformUtilsSetEnv(const char* /* name */, const char* /* value */) {
|
||||||
|
// Stub func
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t /* major_version */, std::string const& /* file_name */) {
|
||||||
|
// Stub func
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
45
thirdparty/openxr/src/common/stdfs_conditions.h
vendored
Normal file
45
thirdparty/openxr/src/common/stdfs_conditions.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
|
||||||
|
#ifndef _STDFS_CONDITIONS_H
|
||||||
|
#define _STDFS_CONDITIONS_H
|
||||||
|
|
||||||
|
// If the C++ macro is set to the version containing C++17, it must support
|
||||||
|
// the final C++17 package
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||||
|
|
||||||
|
#if defined(_HAS_CXX17) && _HAS_CXX17
|
||||||
|
// When MSC supports c++17 use <filesystem> package.
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
#endif // !_HAS_CXX17
|
||||||
|
|
||||||
|
// GCC supports the experimental filesystem items starting in GCC 6
|
||||||
|
#elif (__GNUC__ >= 6)
|
||||||
|
#define USE_EXPERIMENTAL_FS 1
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
|
||||||
|
// If Clang, check for feature support
|
||||||
|
#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
|
||||||
|
#if __cpp_lib_filesystem
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 1
|
||||||
|
#else
|
||||||
|
#define USE_EXPERIMENTAL_FS 1
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If all above fails, fall back to standard C++ and OS-specific items
|
||||||
|
#else
|
||||||
|
#define USE_EXPERIMENTAL_FS 0
|
||||||
|
#define USE_FINAL_FS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !_STDFS_CONDITIONS_H
|
||||||
89
thirdparty/openxr/src/common/xr_dependencies.h
vendored
Normal file
89
thirdparty/openxr/src/common/xr_dependencies.h
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (c) 2018-2022, The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// This file includes headers with types which openxr.h depends on in order
|
||||||
|
// to compile when platforms, graphics apis, and the like are enabled.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include <android/window.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#include <winapifamily.h>
|
||||||
|
#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM))
|
||||||
|
// Enable desktop partition APIs, such as RegOpenKeyEx, LoadLibraryEx, PathFileExists etc.
|
||||||
|
#undef WINAPI_PARTITION_DESKTOP
|
||||||
|
#define WINAPI_PARTITION_DESKTOP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX
|
||||||
|
#endif // !NOMINMAX
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif // !WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <unknwn.h>
|
||||||
|
|
||||||
|
#endif // XR_USE_PLATFORM_WIN32
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D11
|
||||||
|
#include <d3d11.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_D3D11
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||||
|
#include <d3d12.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_D3D12
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XLIB
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
#ifdef Success
|
||||||
|
#undef Success
|
||||||
|
#endif // Success
|
||||||
|
|
||||||
|
#ifdef Always
|
||||||
|
#undef Always
|
||||||
|
#endif // Always
|
||||||
|
|
||||||
|
#ifdef None
|
||||||
|
#undef None
|
||||||
|
#endif // None
|
||||||
|
#endif // XR_USE_PLATFORM_XLIB
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
#if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB)
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#endif // (XR_USE_PLATFORM_XLIB || XR_USE_PLATFORM_XCB)
|
||||||
|
#ifdef XR_USE_PLATFORM_XCB
|
||||||
|
#include <xcb/glx.h>
|
||||||
|
#endif // XR_USE_PLATFORM_XCB
|
||||||
|
#ifdef XR_USE_PLATFORM_MACOS
|
||||||
|
#include <CL/cl_gl_ext.h>
|
||||||
|
#endif // XR_USE_PLATFORM_MACOS
|
||||||
|
#endif // XR_USE_GRAPHICS_API_OPENGL
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_OPENGL_ES
|
||||||
|
|
||||||
|
#ifdef XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#endif // XR_USE_GRAPHICS_API_VULKAN
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_WAYLAND
|
||||||
|
#include "wayland-client.h"
|
||||||
|
#endif // XR_USE_PLATFORM_WAYLAND
|
||||||
787
thirdparty/openxr/src/common/xr_linear.h
vendored
Normal file
787
thirdparty/openxr/src/common/xr_linear.h
vendored
Normal file
@@ -0,0 +1,787 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2016 Oculus VR, LLC.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: J.M.P. van Waveren
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef XR_LINEAR_H_
|
||||||
|
#define XR_LINEAR_H_
|
||||||
|
|
||||||
|
#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX) || defined(OS_LINUX_WAYLAND)
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
================================================================================================
|
||||||
|
|
||||||
|
Description : Vector, matrix and quaternion math.
|
||||||
|
Author : J.M.P. van Waveren
|
||||||
|
Date : 12/10/2016
|
||||||
|
Language : C99
|
||||||
|
Format : Indent 4 spaces - no tabs.
|
||||||
|
Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
===========
|
||||||
|
|
||||||
|
All matrices are column-major.
|
||||||
|
|
||||||
|
INTERFACE
|
||||||
|
=========
|
||||||
|
|
||||||
|
XrVector2f
|
||||||
|
XrVector3f
|
||||||
|
XrVector4f
|
||||||
|
XrQuaternionf
|
||||||
|
XrMatrix4x4f
|
||||||
|
|
||||||
|
inline static void XrVector3f_Set(XrVector3f* v, const float value);
|
||||||
|
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
|
||||||
|
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
|
||||||
|
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
|
||||||
|
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor);
|
||||||
|
inline static void XrVector3f_Normalize(XrVector3f* v);
|
||||||
|
inline static float XrVector3f_Length(const XrVector3f* v);
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
|
||||||
|
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b;
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
|
||||||
|
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
|
||||||
|
const float degreesZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
|
||||||
|
const XrQuaternionf* rotation, const XrVector3f* scale);
|
||||||
|
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, const float tanAngleLeft, const float tanAngleRight,
|
||||||
|
const float tanAngleUp, float const tanAngleDown, const float nearZ,
|
||||||
|
const float farZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, const float fovDegreesLeft, const float fovDegreesRight,
|
||||||
|
const float fovDegreeUp, const float fovDegreesDown, const float nearZ,
|
||||||
|
const float farZ);
|
||||||
|
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* src);
|
||||||
|
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
|
||||||
|
const XrVector3f* maxs);
|
||||||
|
|
||||||
|
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
|
||||||
|
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
|
||||||
|
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
|
||||||
|
|
||||||
|
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
|
||||||
|
const XrVector3f* mins, const XrVector3f* maxs);
|
||||||
|
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
|
||||||
|
|
||||||
|
================================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MATH_PI 3.14159265358979323846f
|
||||||
|
|
||||||
|
#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
|
||||||
|
#define INFINITE_FAR_Z 0.0f
|
||||||
|
|
||||||
|
static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
|
||||||
|
static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
|
||||||
|
|
||||||
|
enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D };
|
||||||
|
|
||||||
|
// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
|
||||||
|
struct XrMatrix4x4f {
|
||||||
|
float m[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static float XrRcpSqrt(const float x) {
|
||||||
|
const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
|
||||||
|
const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
|
||||||
|
return rcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Set(XrVector3f* v, const float value) {
|
||||||
|
v->x = value;
|
||||||
|
v->y = value;
|
||||||
|
v->z = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->x + b->x;
|
||||||
|
result->y = a->y + b->y;
|
||||||
|
result->z = a->z + b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->x - b->x;
|
||||||
|
result->y = a->y - b->y;
|
||||||
|
result->z = a->z - b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = (a->x < b->x) ? a->x : b->x;
|
||||||
|
result->y = (a->y < b->y) ? a->y : b->y;
|
||||||
|
result->z = (a->z < b->z) ? a->z : b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = (a->x > b->x) ? a->x : b->x;
|
||||||
|
result->y = (a->y > b->y) ? a->y : b->y;
|
||||||
|
result->z = (a->z > b->z) ? a->z : b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
|
||||||
|
result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
|
||||||
|
result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
|
||||||
|
result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
|
||||||
|
result->x = a->x + fraction * (b->x - a->x);
|
||||||
|
result->y = a->y + fraction * (b->y - a->y);
|
||||||
|
result->z = a->z + fraction * (b->z - a->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor) {
|
||||||
|
result->x = a->x * scaleFactor;
|
||||||
|
result->y = a->y * scaleFactor;
|
||||||
|
result->z = a->z * scaleFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
|
||||||
|
|
||||||
|
// Compute cross product, which generates a normal vector.
|
||||||
|
// Direction vector can be determined by right-hand rule: Pointing index finder in
|
||||||
|
// direction a and middle finger in direction b, thumb will point in Cross(a, b).
|
||||||
|
inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
|
||||||
|
result->x = a->y * b->z - a->z * b->y;
|
||||||
|
result->y = a->z * b->x - a->x * b->z;
|
||||||
|
result->z = a->x * b->y - a->y * b->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrVector3f_Normalize(XrVector3f* v) {
|
||||||
|
const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
|
||||||
|
v->x *= lengthRcp;
|
||||||
|
v->y *= lengthRcp;
|
||||||
|
v->z *= lengthRcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
|
||||||
|
float s = sinf(angleInRadians / 2.0f);
|
||||||
|
float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
|
||||||
|
result->x = s * axis->x * lengthRcp;
|
||||||
|
result->y = s * axis->y * lengthRcp;
|
||||||
|
result->z = s * axis->z * lengthRcp;
|
||||||
|
result->w = cosf(angleInRadians / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
|
||||||
|
const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
|
||||||
|
const float fa = 1.0f - fraction;
|
||||||
|
const float fb = (s < 0.0f) ? -fraction : fraction;
|
||||||
|
const float x = a->x * fa + b->x * fb;
|
||||||
|
const float y = a->y * fa + b->y * fb;
|
||||||
|
const float z = a->z * fa + b->z * fb;
|
||||||
|
const float w = a->w * fa + b->w * fb;
|
||||||
|
const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
|
||||||
|
result->x = x * lengthRcp;
|
||||||
|
result->y = y * lengthRcp;
|
||||||
|
result->z = z * lengthRcp;
|
||||||
|
result->w = w * lengthRcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b) {
|
||||||
|
result->x = (b->w * a->x) + (b->x * a->w) + (b->y * a->z) - (b->z * a->y);
|
||||||
|
result->y = (b->w * a->y) - (b->x * a->z) + (b->y * a->w) + (b->z * a->x);
|
||||||
|
result->z = (b->w * a->z) + (b->x * a->y) - (b->y * a->x) + (b->z * a->w);
|
||||||
|
result->w = (b->w * a->w) - (b->x * a->x) - (b->y * a->y) - (b->z * a->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use left-multiplication to accumulate transformations.
|
||||||
|
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
|
||||||
|
result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
|
||||||
|
result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
|
||||||
|
result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
|
||||||
|
result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
|
||||||
|
|
||||||
|
result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
|
||||||
|
result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
|
||||||
|
result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
|
||||||
|
result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
|
||||||
|
|
||||||
|
result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
|
||||||
|
result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
|
||||||
|
result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
|
||||||
|
result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
|
||||||
|
|
||||||
|
result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
|
||||||
|
result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
|
||||||
|
result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
|
||||||
|
result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the transpose of the given matrix.
|
||||||
|
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
result->m[0] = src->m[0];
|
||||||
|
result->m[1] = src->m[4];
|
||||||
|
result->m[2] = src->m[8];
|
||||||
|
result->m[3] = src->m[12];
|
||||||
|
|
||||||
|
result->m[4] = src->m[1];
|
||||||
|
result->m[5] = src->m[5];
|
||||||
|
result->m[6] = src->m[9];
|
||||||
|
result->m[7] = src->m[13];
|
||||||
|
|
||||||
|
result->m[8] = src->m[2];
|
||||||
|
result->m[9] = src->m[6];
|
||||||
|
result->m[10] = src->m[10];
|
||||||
|
result->m[11] = src->m[14];
|
||||||
|
|
||||||
|
result->m[12] = src->m[3];
|
||||||
|
result->m[13] = src->m[7];
|
||||||
|
result->m[14] = src->m[11];
|
||||||
|
result->m[15] = src->m[15];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a 3x3 minor of a 4x4 matrix.
|
||||||
|
inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
|
||||||
|
return matrix->m[4 * r0 + c0] *
|
||||||
|
(matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
|
||||||
|
matrix->m[4 * r0 + c1] *
|
||||||
|
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
|
||||||
|
matrix->m[4 * r0 + c2] *
|
||||||
|
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the inverse of a 4x4 matrix.
|
||||||
|
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
const float rcpDet =
|
||||||
|
1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
|
||||||
|
src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
|
||||||
|
|
||||||
|
result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
|
||||||
|
result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
|
||||||
|
result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
|
||||||
|
result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
|
||||||
|
result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the inverse of a rigid body transform.
|
||||||
|
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
|
||||||
|
result->m[0] = src->m[0];
|
||||||
|
result->m[1] = src->m[4];
|
||||||
|
result->m[2] = src->m[8];
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = src->m[1];
|
||||||
|
result->m[5] = src->m[5];
|
||||||
|
result->m[6] = src->m[9];
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = src->m[2];
|
||||||
|
result->m[9] = src->m[6];
|
||||||
|
result->m[10] = src->m[10];
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
|
||||||
|
result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
|
||||||
|
result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an identity matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
|
||||||
|
result->m[0] = 1.0f;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = 1.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = 1.0f;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a translation matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
|
||||||
|
result->m[0] = 1.0f;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = 1.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = 1.0f;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = x;
|
||||||
|
result->m[13] = y;
|
||||||
|
result->m[14] = z;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a rotation matrix.
|
||||||
|
// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
|
||||||
|
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
|
||||||
|
const float degreesZ) {
|
||||||
|
const float sinX = sinf(degreesX * (MATH_PI / 180.0f));
|
||||||
|
const float cosX = cosf(degreesX * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
|
||||||
|
const float sinY = sinf(degreesY * (MATH_PI / 180.0f));
|
||||||
|
const float cosY = cosf(degreesY * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
|
||||||
|
const float sinZ = sinf(degreesZ * (MATH_PI / 180.0f));
|
||||||
|
const float cosZ = cosf(degreesZ * (MATH_PI / 180.0f));
|
||||||
|
const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
|
||||||
|
XrMatrix4x4f rotationXY;
|
||||||
|
XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
|
||||||
|
XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a scale matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
|
||||||
|
result->m[0] = x;
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[5] = y;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[8] = 0.0f;
|
||||||
|
result->m[9] = 0.0f;
|
||||||
|
result->m[10] = z;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a matrix from a quaternion.
|
||||||
|
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
|
||||||
|
const float x2 = quat->x + quat->x;
|
||||||
|
const float y2 = quat->y + quat->y;
|
||||||
|
const float z2 = quat->z + quat->z;
|
||||||
|
|
||||||
|
const float xx2 = quat->x * x2;
|
||||||
|
const float yy2 = quat->y * y2;
|
||||||
|
const float zz2 = quat->z * z2;
|
||||||
|
|
||||||
|
const float yz2 = quat->y * z2;
|
||||||
|
const float wx2 = quat->w * x2;
|
||||||
|
const float xy2 = quat->x * y2;
|
||||||
|
const float wz2 = quat->w * z2;
|
||||||
|
const float xz2 = quat->x * z2;
|
||||||
|
const float wy2 = quat->w * y2;
|
||||||
|
|
||||||
|
result->m[0] = 1.0f - yy2 - zz2;
|
||||||
|
result->m[1] = xy2 + wz2;
|
||||||
|
result->m[2] = xz2 - wy2;
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
|
||||||
|
result->m[4] = xy2 - wz2;
|
||||||
|
result->m[5] = 1.0f - xx2 - zz2;
|
||||||
|
result->m[6] = yz2 + wx2;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
|
||||||
|
result->m[8] = xz2 + wy2;
|
||||||
|
result->m[9] = yz2 - wx2;
|
||||||
|
result->m[10] = 1.0f - xx2 - yy2;
|
||||||
|
result->m[11] = 0.0f;
|
||||||
|
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
result->m[14] = 0.0f;
|
||||||
|
result->m[15] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
|
||||||
|
const XrQuaternionf* rotation, const XrVector3f* scale) {
|
||||||
|
XrMatrix4x4f scaleMatrix;
|
||||||
|
XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
|
||||||
|
|
||||||
|
XrMatrix4x4f rotationMatrix;
|
||||||
|
XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
|
||||||
|
|
||||||
|
XrMatrix4x4f translationMatrix;
|
||||||
|
XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
|
||||||
|
|
||||||
|
XrMatrix4x4f combinedMatrix;
|
||||||
|
XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
|
||||||
|
XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a projection matrix based on the specified dimensions.
|
||||||
|
// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
|
||||||
|
// The far plane is placed at infinity if farZ <= nearZ.
|
||||||
|
// An infinite projection matrix is preferred for rasterization because, except for
|
||||||
|
// things *right* up against the near plane, it always provides better precision:
|
||||||
|
// "Tightening the Precision of Perspective Rendering"
|
||||||
|
// Paul Upchurch, Mathieu Desbrun
|
||||||
|
// Journal of Graphics Tools, Volume 16, Issue 1, 2012
|
||||||
|
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
|
||||||
|
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
|
||||||
|
const float nearZ, const float farZ) {
|
||||||
|
const float tanAngleWidth = tanAngleRight - tanAngleLeft;
|
||||||
|
|
||||||
|
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
|
||||||
|
// Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
|
||||||
|
const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
|
||||||
|
|
||||||
|
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
|
||||||
|
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
|
||||||
|
const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
|
||||||
|
|
||||||
|
if (farZ <= nearZ) {
|
||||||
|
// place the far plane at infinity
|
||||||
|
result->m[0] = 2.0f / tanAngleWidth;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[5] = 2.0f / tanAngleHeight;
|
||||||
|
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[10] = -1.0f;
|
||||||
|
result->m[14] = -(nearZ + offsetZ);
|
||||||
|
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[11] = -1.0f;
|
||||||
|
result->m[15] = 0.0f;
|
||||||
|
} else {
|
||||||
|
// normal projection
|
||||||
|
result->m[0] = 2.0f / tanAngleWidth;
|
||||||
|
result->m[4] = 0.0f;
|
||||||
|
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
|
||||||
|
result->m[12] = 0.0f;
|
||||||
|
|
||||||
|
result->m[1] = 0.0f;
|
||||||
|
result->m[5] = 2.0f / tanAngleHeight;
|
||||||
|
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
|
||||||
|
result->m[13] = 0.0f;
|
||||||
|
|
||||||
|
result->m[2] = 0.0f;
|
||||||
|
result->m[6] = 0.0f;
|
||||||
|
result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
|
||||||
|
result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
|
||||||
|
|
||||||
|
result->m[3] = 0.0f;
|
||||||
|
result->m[7] = 0.0f;
|
||||||
|
result->m[11] = -1.0f;
|
||||||
|
result->m[15] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a projection matrix based on the specified FOV.
|
||||||
|
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
|
||||||
|
const float nearZ, const float farZ) {
|
||||||
|
const float tanLeft = tanf(fov.angleLeft);
|
||||||
|
const float tanRight = tanf(fov.angleRight);
|
||||||
|
|
||||||
|
const float tanDown = tanf(fov.angleDown);
|
||||||
|
const float tanUp = tanf(fov.angleUp);
|
||||||
|
|
||||||
|
XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
|
||||||
|
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
|
||||||
|
const XrVector3f* maxs) {
|
||||||
|
const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
|
||||||
|
const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
|
||||||
|
|
||||||
|
result->m[0] = matrix->m[0] * scale.x;
|
||||||
|
result->m[1] = matrix->m[1] * scale.x;
|
||||||
|
result->m[2] = matrix->m[2] * scale.x;
|
||||||
|
result->m[3] = matrix->m[3] * scale.x;
|
||||||
|
|
||||||
|
result->m[4] = matrix->m[4] * scale.y;
|
||||||
|
result->m[5] = matrix->m[5] * scale.y;
|
||||||
|
result->m[6] = matrix->m[6] * scale.y;
|
||||||
|
result->m[7] = matrix->m[7] * scale.y;
|
||||||
|
|
||||||
|
result->m[8] = matrix->m[8] * scale.z;
|
||||||
|
result->m[9] = matrix->m[9] * scale.z;
|
||||||
|
result->m[10] = matrix->m[10] * scale.z;
|
||||||
|
result->m[11] = matrix->m[11] * scale.z;
|
||||||
|
|
||||||
|
result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
|
||||||
|
result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
|
||||||
|
result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
|
||||||
|
result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is affine.
|
||||||
|
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
|
||||||
|
fabsf(matrix->m[15] - 1.0f) <= epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is orthogonal.
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
if (i != j) {
|
||||||
|
if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
|
||||||
|
matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
|
||||||
|
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is orthonormal.
|
||||||
|
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
|
||||||
|
if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
|
||||||
|
matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
|
||||||
|
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the given matrix is a rigid body transform.
|
||||||
|
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
|
||||||
|
return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the translation from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
result->x = src->m[12];
|
||||||
|
result->y = src->m[13];
|
||||||
|
result->z = src->m[14];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the rotation from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
|
||||||
|
const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
|
||||||
|
const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
|
||||||
|
const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
|
||||||
|
src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
|
||||||
|
src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
|
||||||
|
if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
|
||||||
|
float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->w = s * t;
|
||||||
|
result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
|
||||||
|
result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
|
||||||
|
result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
|
||||||
|
} else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
|
||||||
|
float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->x = s * t;
|
||||||
|
result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
|
||||||
|
result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
|
||||||
|
result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
|
||||||
|
} else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
|
||||||
|
float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->y = s * t;
|
||||||
|
result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
|
||||||
|
result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
|
||||||
|
result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
|
||||||
|
} else {
|
||||||
|
float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
|
||||||
|
float s = XrRcpSqrt(t) * 0.5f;
|
||||||
|
result->z = s * t;
|
||||||
|
result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
|
||||||
|
result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
|
||||||
|
result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the scale from a combined translation(rotation(scale(object))) matrix.
|
||||||
|
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
|
||||||
|
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
|
||||||
|
|
||||||
|
result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
|
||||||
|
result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
|
||||||
|
result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a 3D vector.
|
||||||
|
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
|
||||||
|
const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
|
||||||
|
const float rcpW = 1.0f / w;
|
||||||
|
result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
|
||||||
|
result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
|
||||||
|
result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms a 4D vector.
|
||||||
|
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
|
||||||
|
result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
|
||||||
|
result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
|
||||||
|
result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
|
||||||
|
result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
|
||||||
|
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
|
||||||
|
const XrVector3f* mins, const XrVector3f* maxs) {
|
||||||
|
assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
|
||||||
|
|
||||||
|
const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
|
||||||
|
const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
|
||||||
|
const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
|
||||||
|
matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
|
||||||
|
matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
|
||||||
|
const XrVector3f newExtents = {
|
||||||
|
fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
|
||||||
|
fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
|
||||||
|
fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
|
||||||
|
XrVector3f_Sub(resultMins, &newCenter, &newExtents);
|
||||||
|
XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
|
||||||
|
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
|
||||||
|
if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrVector4f c[8];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
const XrVector4f corner = {(i & 1) != 0 ? maxs->x : mins->x, (i & 2) != 0 ? maxs->y : mins->y,
|
||||||
|
(i & 4) != 0 ? maxs->z : mins->z, 1.0f};
|
||||||
|
XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].x > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].x < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].y > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].y < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].z > -c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (c[i].z < c[i].w) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i == 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XR_LINEAR_H_
|
||||||
115
thirdparty/openxr/src/external/jsoncpp/AUTHORS
vendored
Normal file
115
thirdparty/openxr/src/external/jsoncpp/AUTHORS
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
Baptiste Lepilleur <blep@users.sourceforge.net>
|
||||||
|
|
||||||
|
Aaron Jacobs <aaronjjacobs@gmail.com>
|
||||||
|
Aaron Jacobs <jacobsa@google.com>
|
||||||
|
Adam Boseley <ABoseley@agjunction.com>
|
||||||
|
Adam Boseley <adam.boseley@gmail.com>
|
||||||
|
Aleksandr Derbenev <13alexac@gmail.com>
|
||||||
|
Alexander Gazarov <DrMetallius@users.noreply.github.com>
|
||||||
|
Alexander V. Brezgin <abrezgin@appliedtech.ru>
|
||||||
|
Alexandr Brezgin <albrezgin@mail.ru>
|
||||||
|
Alexey Kruchinin <alexey@mopals.com>
|
||||||
|
Anton Indrawan <anton.indrawan@gmail.com>
|
||||||
|
Baptiste Jonglez <git@bitsofnetworks.org>
|
||||||
|
Baptiste Lepilleur <baptiste.lepilleur@gmail.com>
|
||||||
|
Baruch Siach <baruch@tkos.co.il>
|
||||||
|
Ben Boeckel <mathstuf@gmail.com>
|
||||||
|
Benjamin Knecht <bknecht@logitech.com>
|
||||||
|
Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||||
|
Billy Donahue <billydonahue@google.com>
|
||||||
|
Braden McDorman <bmcdorman@gmail.com>
|
||||||
|
Brandon Myers <bmyers1788@gmail.com>
|
||||||
|
Brendan Drew <brendan.drew@daqri.com>
|
||||||
|
chason <cxchao802@gmail.com>
|
||||||
|
chenguoping <chenguopingdota@163.com>
|
||||||
|
Chris Gilling <cgilling@iparadigms.com>
|
||||||
|
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||||
|
Christopher Dunn <cdunn2001@gmail.com>
|
||||||
|
Chuck Atkins <chuck.atkins@kitware.com>
|
||||||
|
Cody P Schafer <dev@codyps.com>
|
||||||
|
Connor Manning <connor@hobu.co>
|
||||||
|
Cory Quammen <cory.quammen@kitware.com>
|
||||||
|
Cristóvão B da Cruz e Silva <CrisXed@gmail.com>
|
||||||
|
Daniel Krügler <daniel.kruegler@gmail.com>
|
||||||
|
Dani-Hub <daniel.kruegler@googlemail.com>
|
||||||
|
Dan Liu <gzliudan>
|
||||||
|
datadiode <datadiode@users.noreply.github.com>
|
||||||
|
datadiode <jochen.neubeck@vodafone.de>
|
||||||
|
David Seifert <soap@gentoo.org>
|
||||||
|
David West <david-west@idexx.com>
|
||||||
|
dawesc <chris.dawes@eftlab.co.uk>
|
||||||
|
Devin Jeanpierre <jeanpierreda@google.com>
|
||||||
|
Dmitry Marakasov <amdmi3@amdmi3.ru>
|
||||||
|
dominicpezzuto <dom@dompezzuto.com>
|
||||||
|
Don Milham <dmilham@gmail.com>
|
||||||
|
drgler <daniel.kruegler@gmail.com>
|
||||||
|
ds283 <D.Seery@sussex.ac.uk>
|
||||||
|
Egor Tensin <Egor.Tensin@gmail.com>
|
||||||
|
eightnoteight <mr.eightnoteight@gmail.com>
|
||||||
|
Evince <baneyue@gmail.com>
|
||||||
|
filipjs <filipjs@users.noreply.github.com>
|
||||||
|
findblar <ft@finbarr.ca>
|
||||||
|
Florian Meier <florian.meier@koalo.de>
|
||||||
|
Gaëtan Lehmann <gaetan.lehmann@gmail.com>
|
||||||
|
Gaurav <g.gupta@samsung.com>
|
||||||
|
Gergely Nagy <ngg@ngg.hu>
|
||||||
|
Gida Pataki <gida.pataki@prezi.com>
|
||||||
|
I3ck <buckmartin@buckmartin.de>
|
||||||
|
Iñaki Baz Castillo <ibc@aliax.net>
|
||||||
|
Jacco <jacco@geul.net>
|
||||||
|
Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
|
||||||
|
Jonas Platte <mail@jonasplatte.de>
|
||||||
|
Jordan Bayles <bayles.jordan@gmail.com>
|
||||||
|
Jörg Krause <joerg.krause@embedded.rocks>
|
||||||
|
Keith Lea <keith@whamcitylights.com>
|
||||||
|
Kevin Grant <kbradleygrant@gmail.com>
|
||||||
|
Kirill V. Lyadvinsky <jia3ep@gmail.com>
|
||||||
|
Kirill V. Lyadvinsky <mail@codeatcpp.com>
|
||||||
|
Kobi Gurkan <kobigurk@gmail.com>
|
||||||
|
Magnus Bjerke Vik <mbvett@gmail.com>
|
||||||
|
Malay Shah <malays@users.sourceforge.net>
|
||||||
|
Mara Kim <hacker.root@gmail.com>
|
||||||
|
Marek Kotewicz <marek.kotewicz@gmail.com>
|
||||||
|
Mark Lakata <mark@lakata.org>
|
||||||
|
Mark Zeren <mzeren@vmware.com>
|
||||||
|
Martin Buck <buckmartin@buckmartin.de>
|
||||||
|
Martyn Gigg <martyn.gigg@gmail.com>
|
||||||
|
Mattes D <github@xoft.cz>
|
||||||
|
Matthias Loy <matthias.loy@hbm.com>
|
||||||
|
Merlyn Morgan-Graham <kavika@gmail.com>
|
||||||
|
Michael Shields <mshields@google.com>
|
||||||
|
Michał Górny <mgorny@gentoo.org>
|
||||||
|
Mike Naberezny <mike@naberezny.com>
|
||||||
|
mloy <matthias.loy@googlemail.com>
|
||||||
|
Motti <lanzkron@gmail.com>
|
||||||
|
nnkur <nnkur@mail.ru>
|
||||||
|
Omkar Wagh <owagh@owaghlinux.ny.tower-research.com>
|
||||||
|
paulo <paulobrizolara@users.noreply.github.com>
|
||||||
|
pavel.pimenov <pavel.pimenov@gmail.com>
|
||||||
|
Paweł Bylica <chfast@gmail.com>
|
||||||
|
Péricles Lopes Machado <pericles.raskolnikoff@gmail.com>
|
||||||
|
Peter Spiess-Knafl <psk@autistici.org>
|
||||||
|
pffang <pffang@vip.qq.com>
|
||||||
|
Rémi Verschelde <remi@verschelde.fr>
|
||||||
|
renu555 <renu.tyagi@samsung.com>
|
||||||
|
Robert Dailey <rcdailey@gmail.com>
|
||||||
|
Sam Clegg <sbc@chromium.org>
|
||||||
|
selaselah <selah@outlook.com>
|
||||||
|
Sergiy80 <sil2004@gmail.com>
|
||||||
|
sergzub <sergzub@gmail.com>
|
||||||
|
Stefan Schweter <stefan@schweter.it>
|
||||||
|
Stefano Fiorentino <stefano.fiore84@gmail.com>
|
||||||
|
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
||||||
|
Steven Hahn <hahnse@ornl.gov>
|
||||||
|
Stuart Eichert <stuart@fivemicro.com>
|
||||||
|
SuperManitu <supermanitu@gmail.com>
|
||||||
|
Techwolf <dring@g33kworld.net>
|
||||||
|
Tengiz Sharafiev <btolfa+github@gmail.com>
|
||||||
|
Tomasz Maciejewski <tmaciejewsk@gmail.com>
|
||||||
|
Vicente Olivert Riera <Vincent.Riera@imgtec.com>
|
||||||
|
xiaoyur347 <xiaoyur347@gmail.com>
|
||||||
|
ycqiu <429148848@qq.com>
|
||||||
|
yiqiju <fred_ju@selinc.com>
|
||||||
|
Yu Xiaolei <dreifachstein@gmail.com>
|
||||||
|
|
||||||
|
Google Inc.
|
||||||
55
thirdparty/openxr/src/external/jsoncpp/LICENSE
vendored
Normal file
55
thirdparty/openxr/src/external/jsoncpp/LICENSE
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
The JsonCpp library's source code, including accompanying documentation,
|
||||||
|
tests and demonstration applications, are licensed under the following
|
||||||
|
conditions...
|
||||||
|
|
||||||
|
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||||
|
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||||
|
this software is released into the Public Domain.
|
||||||
|
|
||||||
|
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||||
|
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||||
|
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||||
|
|
||||||
|
In jurisdictions which recognize Public Domain property, the user of this
|
||||||
|
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||||
|
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||||
|
Public Domain/MIT License conditions described here, as they choose.
|
||||||
|
|
||||||
|
The MIT License is about as close to Public Domain as a license can get, and is
|
||||||
|
described in clear, concise terms at:
|
||||||
|
|
||||||
|
http://en.wikipedia.org/wiki/MIT_License
|
||||||
|
|
||||||
|
The full text of the MIT License follows:
|
||||||
|
|
||||||
|
========================================================================
|
||||||
|
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
========================================================================
|
||||||
|
(END LICENSE TEXT)
|
||||||
|
|
||||||
|
The MIT license is compatible with both the GPL and commercial
|
||||||
|
software, affording one all of the rights of Public Domain with the
|
||||||
|
minor nuisance of being required to keep the above copyright notice
|
||||||
|
and license text in the source code. Note also that by accepting the
|
||||||
|
Public Domain "license" you can re-license your copy using whatever
|
||||||
|
license you like.
|
||||||
88
thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h
vendored
Normal file
88
thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
#define JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
template <typename T> class SecureAllocator {
|
||||||
|
public:
|
||||||
|
// Type definitions
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for N items using the standard allocator.
|
||||||
|
*/
|
||||||
|
pointer allocate(size_type n) {
|
||||||
|
// allocate using "global operator new"
|
||||||
|
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release memory which was allocated for N items at pointer P.
|
||||||
|
*
|
||||||
|
* The memory block is filled with zeroes before being released.
|
||||||
|
*/
|
||||||
|
void deallocate(pointer p, size_type n) {
|
||||||
|
// memset_s is used because memset may be optimized away by the compiler
|
||||||
|
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||||
|
// free using "global operator delete"
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
template <typename... Args> void construct(pointer p, Args&&... args) {
|
||||||
|
// construct using "placement new" and "perfect forwarding"
|
||||||
|
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_size() const { return size_t(-1) / sizeof(T); }
|
||||||
|
|
||||||
|
pointer address(reference x) const { return std::addressof(x); }
|
||||||
|
|
||||||
|
const_pointer address(const_reference x) const { return std::addressof(x); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
void destroy(pointer p) {
|
||||||
|
// destroy using "explicit destructor"
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boilerplate
|
||||||
|
SecureAllocator() {}
|
||||||
|
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
|
template <typename U> struct rebind { using other = SecureAllocator<U>; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // JSON_ALLOCATOR_H_INCLUDED
|
||||||
61
thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h
vendored
Normal file
61
thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
#define JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "config.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
/** It should not be possible for a maliciously designed file to
|
||||||
|
* cause an abort() or seg-fault, so these macros are used only
|
||||||
|
* for pre-condition violations and internal logic errors.
|
||||||
|
*/
|
||||||
|
#if JSON_USE_EXCEPTION
|
||||||
|
|
||||||
|
// @todo <= add detail about condition in exception
|
||||||
|
#define JSON_ASSERT(condition) \
|
||||||
|
do { \
|
||||||
|
if (!(condition)) { \
|
||||||
|
Json::throwLogicError("assert json failed"); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define JSON_FAIL_MESSAGE(message) \
|
||||||
|
do { \
|
||||||
|
OStringStream oss; \
|
||||||
|
oss << message; \
|
||||||
|
Json::throwLogicError(oss.str()); \
|
||||||
|
abort(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else // JSON_USE_EXCEPTION
|
||||||
|
|
||||||
|
#define JSON_ASSERT(condition) assert(condition)
|
||||||
|
|
||||||
|
// The call to assert() will show the failure message in debug builds. In
|
||||||
|
// release builds we abort, for a core-dump or debugger.
|
||||||
|
#define JSON_FAIL_MESSAGE(message) \
|
||||||
|
{ \
|
||||||
|
OStringStream oss; \
|
||||||
|
oss << message; \
|
||||||
|
assert(false && oss.str().c_str()); \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
|
do { \
|
||||||
|
if (!(condition)) { \
|
||||||
|
JSON_FAIL_MESSAGE(message); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif // JSON_ASSERTIONS_H_INCLUDED
|
||||||
150
thirdparty/openxr/src/external/jsoncpp/include/json/config.h
vendored
Normal file
150
thirdparty/openxr/src/external/jsoncpp/include/json/config.h
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <istream>
|
||||||
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
|
// assertion macros. The default is to use exceptions.
|
||||||
|
#ifndef JSON_USE_EXCEPTION
|
||||||
|
#define JSON_USE_EXCEPTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Temporary, tracked for removal with issue #982.
|
||||||
|
#ifndef JSON_USE_NULLREF
|
||||||
|
#define JSON_USE_NULLREF 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// If defined, indicates that the source file is amalgamated
|
||||||
|
/// to prevent private header inclusion.
|
||||||
|
/// Remarks: it is automatically defined in the generated amalgamated header.
|
||||||
|
// #define JSON_IS_AMALGAMATION
|
||||||
|
|
||||||
|
// Export macros for DLL visibility
|
||||||
|
#if defined(JSON_DLL_BUILD)
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define JSON_API __declspec(dllexport)
|
||||||
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define JSON_API __attribute__((visibility("default")))
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
|
#elif defined(JSON_DLL)
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define JSON_API __declspec(dllimport)
|
||||||
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
#endif // ifdef JSON_DLL_BUILD
|
||||||
|
|
||||||
|
#if !defined(JSON_API)
|
||||||
|
#define JSON_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||||
|
#error \
|
||||||
|
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
// As recommended at
|
||||||
|
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
||||||
|
extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
||||||
|
const char* format, ...);
|
||||||
|
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
|
||||||
|
#else
|
||||||
|
#define jsoncpp_snprintf std::snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||||
|
// integer
|
||||||
|
// Storages, and 64 bits integer support is disabled.
|
||||||
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
|
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
|
||||||
|
// C++11 should be used directly in JSONCPP.
|
||||||
|
#define JSONCPP_OVERRIDE override
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __has_extension(attribute_deprecated_with_message)
|
||||||
|
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||||
|
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||||
|
#endif // GNUC version
|
||||||
|
#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
|
||||||
|
// MSVC)
|
||||||
|
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
#endif // __clang__ || __GNUC__ || _MSC_VER
|
||||||
|
|
||||||
|
#if !defined(JSONCPP_DEPRECATED)
|
||||||
|
#define JSONCPP_DEPRECATED(message)
|
||||||
|
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||||
|
|
||||||
|
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
|
||||||
|
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
#include "allocator.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
using Int = int;
|
||||||
|
using UInt = unsigned int;
|
||||||
|
#if defined(JSON_NO_INT64)
|
||||||
|
using LargestInt = int;
|
||||||
|
using LargestUInt = unsigned int;
|
||||||
|
#undef JSON_HAS_INT64
|
||||||
|
#else // if defined(JSON_NO_INT64)
|
||||||
|
// For Microsoft Visual use specific types as long long is not supported
|
||||||
|
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||||
|
using Int64 = __int64;
|
||||||
|
using UInt64 = unsigned __int64;
|
||||||
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
|
using Int64 = int64_t;
|
||||||
|
using UInt64 = uint64_t;
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
using LargestInt = Int64;
|
||||||
|
using LargestUInt = UInt64;
|
||||||
|
#define JSON_HAS_INT64
|
||||||
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using Allocator =
|
||||||
|
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
||||||
|
std::allocator<T>>::type;
|
||||||
|
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
||||||
|
using IStringStream =
|
||||||
|
std::basic_istringstream<String::value_type, String::traits_type,
|
||||||
|
String::allocator_type>;
|
||||||
|
using OStringStream =
|
||||||
|
std::basic_ostringstream<String::value_type, String::traits_type,
|
||||||
|
String::allocator_type>;
|
||||||
|
using IStream = std::istream;
|
||||||
|
using OStream = std::ostream;
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
// Legacy names (formerly macros).
|
||||||
|
using JSONCPP_STRING = Json::String;
|
||||||
|
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
|
||||||
|
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
|
||||||
|
using JSONCPP_ISTREAM = Json::IStream;
|
||||||
|
using JSONCPP_OSTREAM = Json::OStream;
|
||||||
|
|
||||||
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
43
thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h
vendored
Normal file
43
thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||||
|
#define JSON_FORWARDS_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "config.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
// writer.h
|
||||||
|
class StreamWriter;
|
||||||
|
class StreamWriterBuilder;
|
||||||
|
class Writer;
|
||||||
|
class FastWriter;
|
||||||
|
class StyledWriter;
|
||||||
|
class StyledStreamWriter;
|
||||||
|
|
||||||
|
// reader.h
|
||||||
|
class Reader;
|
||||||
|
class CharReader;
|
||||||
|
class CharReaderBuilder;
|
||||||
|
|
||||||
|
// json_features.h
|
||||||
|
class Features;
|
||||||
|
|
||||||
|
// value.h
|
||||||
|
using ArrayIndex = unsigned int;
|
||||||
|
class StaticString;
|
||||||
|
class Path;
|
||||||
|
class PathArgument;
|
||||||
|
class Value;
|
||||||
|
class ValueIteratorBase;
|
||||||
|
class ValueIterator;
|
||||||
|
class ValueConstIterator;
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_FORWARDS_H_INCLUDED
|
||||||
15
thirdparty/openxr/src/external/jsoncpp/include/json/json.h
vendored
Normal file
15
thirdparty/openxr/src/external/jsoncpp/include/json/json.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_JSON_H_INCLUDED
|
||||||
|
#define JSON_JSON_H_INCLUDED
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "json_features.h"
|
||||||
|
#include "reader.h"
|
||||||
|
#include "value.h"
|
||||||
|
#include "writer.h"
|
||||||
|
|
||||||
|
#endif // JSON_JSON_H_INCLUDED
|
||||||
61
thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h
vendored
Normal file
61
thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_FEATURES_H_INCLUDED
|
||||||
|
#define JSON_FEATURES_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "forwards.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
/** \brief Configuration passed to reader and writer.
|
||||||
|
* This configuration object can be used to force the Reader or Writer
|
||||||
|
* to behave in a standard conforming way.
|
||||||
|
*/
|
||||||
|
class JSON_API Features {
|
||||||
|
public:
|
||||||
|
/** \brief A configuration that allows all features and assumes all strings
|
||||||
|
* are UTF-8.
|
||||||
|
* - C & C++ comments are allowed
|
||||||
|
* - Root object can be any JSON value
|
||||||
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
|
*/
|
||||||
|
static Features all();
|
||||||
|
|
||||||
|
/** \brief A configuration that is strictly compatible with the JSON
|
||||||
|
* specification.
|
||||||
|
* - Comments are forbidden.
|
||||||
|
* - Root object must be either an array or an object value.
|
||||||
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
|
*/
|
||||||
|
static Features strictMode();
|
||||||
|
|
||||||
|
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||||
|
*/
|
||||||
|
Features();
|
||||||
|
|
||||||
|
/// \c true if comments are allowed. Default: \c true.
|
||||||
|
bool allowComments_{true};
|
||||||
|
|
||||||
|
/// \c true if root must be either an array or an object value. Default: \c
|
||||||
|
/// false.
|
||||||
|
bool strictRoot_{false};
|
||||||
|
|
||||||
|
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||||
|
bool allowDroppedNullPlaceholders_{false};
|
||||||
|
|
||||||
|
/// \c true if numeric object key are allowed. Default: \c false.
|
||||||
|
bool allowNumericKeys_{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // JSON_FEATURES_H_INCLUDED
|
||||||
405
thirdparty/openxr/src/external/jsoncpp/include/json/reader.h
vendored
Normal file
405
thirdparty/openxr/src/external/jsoncpp/include/json/reader.h
vendored
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_READER_H_INCLUDED
|
||||||
|
#define JSON_READER_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "json_features.h"
|
||||||
|
#include "value.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <deque>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <istream>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||||
|
* Value.
|
||||||
|
*
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class JSON_API Reader {
|
||||||
|
public:
|
||||||
|
using Char = char;
|
||||||
|
using Location = const Char*;
|
||||||
|
|
||||||
|
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||||
|
*
|
||||||
|
* The offsets give the [start, limit) range of bytes within the text. Note
|
||||||
|
* that this is bytes, not codepoints.
|
||||||
|
*/
|
||||||
|
struct StructuredError {
|
||||||
|
ptrdiff_t offset_start;
|
||||||
|
ptrdiff_t offset_limit;
|
||||||
|
String message;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing all features for parsing.
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
|
*/
|
||||||
|
Reader();
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
|
*/
|
||||||
|
Reader(const Features& features);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* \param document UTF-8 encoded string containing the document
|
||||||
|
* to read.
|
||||||
|
* \param[out] root Contains the root value of the document if it
|
||||||
|
* was successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing
|
||||||
|
* them back during serialization, \c false to
|
||||||
|
* discard comments. This parameter is ignored
|
||||||
|
* if Features::allowComments_ is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
* error occurred.
|
||||||
|
*/
|
||||||
|
bool parse(const std::string& document, Value& root,
|
||||||
|
bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded
|
||||||
|
* string of the document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string
|
||||||
|
* of the document to read. Must be >= beginDoc.
|
||||||
|
* \param[out] root Contains the root value of the document if it
|
||||||
|
* was successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing
|
||||||
|
* them back during serialization, \c false to
|
||||||
|
* discard comments. This parameter is ignored
|
||||||
|
* if Features::allowComments_ is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
* error occurred.
|
||||||
|
*/
|
||||||
|
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
|
bool collectComments = true);
|
||||||
|
|
||||||
|
/// \brief Parse from input stream.
|
||||||
|
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||||
|
bool parse(IStream& is, Value& root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* \return Formatted error message with the list of errors with their
|
||||||
|
* location in the parsed document. An empty string is returned if no error
|
||||||
|
* occurred during parsing.
|
||||||
|
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||||
|
*/
|
||||||
|
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
|
||||||
|
String getFormatedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* \return Formatted error message with the list of errors with their
|
||||||
|
* location in the parsed document. An empty string is returned if no error
|
||||||
|
* occurred during parsing.
|
||||||
|
*/
|
||||||
|
String getFormattedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a vector of structured errors encountered while parsing.
|
||||||
|
*
|
||||||
|
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||||
|
* only one error can be returned, but the caller should tolerate multiple
|
||||||
|
* errors. This can occur if the parser recovers from a non-fatal parse
|
||||||
|
* error and then encounters additional errors.
|
||||||
|
*/
|
||||||
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
|
/** \brief Add a semantic error message.
|
||||||
|
*
|
||||||
|
* \param value JSON Value location associated with the error
|
||||||
|
* \param message The error message.
|
||||||
|
* \return \c true if the error was successfully added, \c false if the Value
|
||||||
|
* offset exceeds the document size.
|
||||||
|
*/
|
||||||
|
bool pushError(const Value& value, const String& message);
|
||||||
|
|
||||||
|
/** \brief Add a semantic error message with extra context.
|
||||||
|
*
|
||||||
|
* \param value JSON Value location associated with the error
|
||||||
|
* \param message The error message.
|
||||||
|
* \param extra Additional JSON Value location to contextualize the error
|
||||||
|
* \return \c true if the error was successfully added, \c false if either
|
||||||
|
* Value offset exceeds the document size.
|
||||||
|
*/
|
||||||
|
bool pushError(const Value& value, const String& message, const Value& extra);
|
||||||
|
|
||||||
|
/** \brief Return whether there are any errors.
|
||||||
|
*
|
||||||
|
* \return \c true if there are no errors to report \c false if errors have
|
||||||
|
* occurred.
|
||||||
|
*/
|
||||||
|
bool good() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum TokenType {
|
||||||
|
tokenEndOfStream = 0,
|
||||||
|
tokenObjectBegin,
|
||||||
|
tokenObjectEnd,
|
||||||
|
tokenArrayBegin,
|
||||||
|
tokenArrayEnd,
|
||||||
|
tokenString,
|
||||||
|
tokenNumber,
|
||||||
|
tokenTrue,
|
||||||
|
tokenFalse,
|
||||||
|
tokenNull,
|
||||||
|
tokenArraySeparator,
|
||||||
|
tokenMemberSeparator,
|
||||||
|
tokenComment,
|
||||||
|
tokenError
|
||||||
|
};
|
||||||
|
|
||||||
|
class Token {
|
||||||
|
public:
|
||||||
|
TokenType type_;
|
||||||
|
Location start_;
|
||||||
|
Location end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorInfo {
|
||||||
|
public:
|
||||||
|
Token token_;
|
||||||
|
String message_;
|
||||||
|
Location extra_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Errors = std::deque<ErrorInfo>;
|
||||||
|
|
||||||
|
bool readToken(Token& token);
|
||||||
|
void skipSpaces();
|
||||||
|
bool match(const Char* pattern, int patternLength);
|
||||||
|
bool readComment();
|
||||||
|
bool readCStyleComment();
|
||||||
|
bool readCppStyleComment();
|
||||||
|
bool readString();
|
||||||
|
void readNumber();
|
||||||
|
bool readValue();
|
||||||
|
bool readObject(Token& token);
|
||||||
|
bool readArray(Token& token);
|
||||||
|
bool decodeNumber(Token& token);
|
||||||
|
bool decodeNumber(Token& token, Value& decoded);
|
||||||
|
bool decodeString(Token& token);
|
||||||
|
bool decodeString(Token& token, String& decoded);
|
||||||
|
bool decodeDouble(Token& token);
|
||||||
|
bool decodeDouble(Token& token, Value& decoded);
|
||||||
|
bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
|
||||||
|
unsigned int& unicode);
|
||||||
|
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||||
|
Location end, unsigned int& unicode);
|
||||||
|
bool addError(const String& message, Token& token, Location extra = nullptr);
|
||||||
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
|
bool addErrorAndRecover(const String& message, Token& token,
|
||||||
|
TokenType skipUntilToken);
|
||||||
|
void skipUntilSpace();
|
||||||
|
Value& currentValue();
|
||||||
|
Char getNextChar();
|
||||||
|
void getLocationLineAndColumn(Location location, int& line,
|
||||||
|
int& column) const;
|
||||||
|
String getLocationLineAndColumn(Location location) const;
|
||||||
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
|
void skipCommentTokens(Token& token);
|
||||||
|
|
||||||
|
static bool containsNewLine(Location begin, Location end);
|
||||||
|
static String normalizeEOL(Location begin, Location end);
|
||||||
|
|
||||||
|
using Nodes = std::stack<Value*>;
|
||||||
|
Nodes nodes_;
|
||||||
|
Errors errors_;
|
||||||
|
String document_;
|
||||||
|
Location begin_{};
|
||||||
|
Location end_{};
|
||||||
|
Location current_{};
|
||||||
|
Location lastValueEnd_{};
|
||||||
|
Value* lastValue_{};
|
||||||
|
String commentsBefore_;
|
||||||
|
Features features_;
|
||||||
|
bool collectComments_{};
|
||||||
|
}; // Reader
|
||||||
|
|
||||||
|
/** Interface for reading JSON from a char array.
|
||||||
|
*/
|
||||||
|
class JSON_API CharReader {
|
||||||
|
public:
|
||||||
|
virtual ~CharReader() = default;
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
* document. The document must be a UTF-8 encoded string containing the
|
||||||
|
* document to read.
|
||||||
|
*
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string
|
||||||
|
* of the document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
|
* document to read. Must be >= beginDoc.
|
||||||
|
* \param[out] root Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param[out] errs Formatted error messages (if not NULL) a user
|
||||||
|
* friendly string that lists errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
* error occurred.
|
||||||
|
*/
|
||||||
|
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) = 0;
|
||||||
|
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory() = default;
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual CharReader* newCharReader() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // CharReader
|
||||||
|
|
||||||
|
/** \brief Build a CharReader implementation.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* \code
|
||||||
|
* using namespace Json;
|
||||||
|
* CharReaderBuilder builder;
|
||||||
|
* builder["collectComments"] = false;
|
||||||
|
* Value value;
|
||||||
|
* String errs;
|
||||||
|
* bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class JSON_API CharReaderBuilder : public CharReader::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
* These are case-sensitive.
|
||||||
|
* Available settings (case-sensitive):
|
||||||
|
* - `"collectComments": false or true`
|
||||||
|
* - true to collect comment and allow writing them back during
|
||||||
|
* serialization, false to discard comments. This parameter is ignored
|
||||||
|
* if allowComments is false.
|
||||||
|
* - `"allowComments": false or true`
|
||||||
|
* - true if comments are allowed.
|
||||||
|
* - `"allowTrailingCommas": false or true`
|
||||||
|
* - true if trailing commas in objects and arrays are allowed.
|
||||||
|
* - `"strictRoot": false or true`
|
||||||
|
* - true if root must be either an array or an object value
|
||||||
|
* - `"allowDroppedNullPlaceholders": false or true`
|
||||||
|
* - true if dropped null placeholders are allowed. (See
|
||||||
|
* StreamWriterBuilder.)
|
||||||
|
* - `"allowNumericKeys": false or true`
|
||||||
|
* - true if numeric object keys are allowed.
|
||||||
|
* - `"allowSingleQuotes": false or true`
|
||||||
|
* - true if '' are allowed for strings (both keys and values)
|
||||||
|
* - `"stackLimit": integer`
|
||||||
|
* - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
|
||||||
|
* exception.
|
||||||
|
* - This is a security issue (seg-faults caused by deeply nested JSON), so
|
||||||
|
* the default is low.
|
||||||
|
* - `"failIfExtra": false or true`
|
||||||
|
* - If true, `parse()` returns false when extra non-whitespace trails the
|
||||||
|
* JSON value in the input string.
|
||||||
|
* - `"rejectDupKeys": false or true`
|
||||||
|
* - If true, `parse()` returns false when a key is duplicated within an
|
||||||
|
* object.
|
||||||
|
* - `"allowSpecialFloats": false or true`
|
||||||
|
* - If true, special float values (NaNs and infinities) are allowed and
|
||||||
|
* their values are lossfree restorable.
|
||||||
|
* - `"skipBom": false or true`
|
||||||
|
* - If true, if the input starts with the Unicode byte order mark (BOM),
|
||||||
|
* it is skipped.
|
||||||
|
*
|
||||||
|
* You can examine 'settings_` yourself to see the defaults. You can also
|
||||||
|
* write and read them just like any JSON Value.
|
||||||
|
* \sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
CharReaderBuilder();
|
||||||
|
~CharReaderBuilder() override;
|
||||||
|
|
||||||
|
CharReader* newCharReader() const override;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](const String& key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
/** Same as old Features::strictMode().
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
|
*/
|
||||||
|
static void strictMode(Json::Value* settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Consume entire stream and use its begin/end.
|
||||||
|
* Someday we might have a real StreamReader, but for now this
|
||||||
|
* is convenient.
|
||||||
|
*/
|
||||||
|
bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
|
||||||
|
String* errs);
|
||||||
|
|
||||||
|
/** \brief Read from 'sin' into 'root'.
|
||||||
|
*
|
||||||
|
* Always keep comments from the input JSON.
|
||||||
|
*
|
||||||
|
* This can be used to read a file into a particular sub-object.
|
||||||
|
* For example:
|
||||||
|
* \code
|
||||||
|
* Json::Value root;
|
||||||
|
* cin >> root["dir"]["file"];
|
||||||
|
* cout << root;
|
||||||
|
* \endcode
|
||||||
|
* Result:
|
||||||
|
* \verbatim
|
||||||
|
* {
|
||||||
|
* "dir": {
|
||||||
|
* "file": {
|
||||||
|
* // The input stream JSON would be nested here.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* \endverbatim
|
||||||
|
* \throw std::exception on parse error.
|
||||||
|
* \see Json::operator<<()
|
||||||
|
*/
|
||||||
|
JSON_API IStream& operator>>(IStream&, Value&);
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // JSON_READER_H_INCLUDED
|
||||||
935
thirdparty/openxr/src/external/jsoncpp/include/json/value.h
vendored
Normal file
935
thirdparty/openxr/src/external/jsoncpp/include/json/value.h
vendored
Normal file
@@ -0,0 +1,935 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_H_INCLUDED
|
||||||
|
#define JSON_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "forwards.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
// Conditional NORETURN attribute on the throw functions would:
|
||||||
|
// a) suppress false positives from static code analysis
|
||||||
|
// b) possibly improve optimization opportunities.
|
||||||
|
#if !defined(JSONCPP_NORETURN)
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER == 1800
|
||||||
|
#define JSONCPP_NORETURN __declspec(noreturn)
|
||||||
|
#else
|
||||||
|
#define JSONCPP_NORETURN [[noreturn]]
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Support for '= delete' with template declarations was a late addition
|
||||||
|
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
|
||||||
|
// even though these declare themselves to be c++11 compilers.
|
||||||
|
#if !defined(JSONCPP_TEMPLATE_DELETE)
|
||||||
|
#if defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
#if __apple_build_version__ <= 8000042
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#endif
|
||||||
|
#elif defined(__clang__)
|
||||||
|
#if __clang_major__ == 3 && __clang_minor__ <= 8
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if !defined(JSONCPP_TEMPLATE_DELETE)
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE = delete
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <exception>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
/** \brief JSON (JavaScript Object Notation).
|
||||||
|
*/
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
#if JSON_USE_EXCEPTION
|
||||||
|
/** Base class for all exceptions we throw.
|
||||||
|
*
|
||||||
|
* We use nothing but these internally. Of course, STL can throw others.
|
||||||
|
*/
|
||||||
|
class JSON_API Exception : public std::exception {
|
||||||
|
public:
|
||||||
|
Exception(String msg);
|
||||||
|
~Exception() noexcept override;
|
||||||
|
char const* what() const noexcept override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
String msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions which the user cannot easily avoid.
|
||||||
|
*
|
||||||
|
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API RuntimeError : public Exception {
|
||||||
|
public:
|
||||||
|
RuntimeError(String const& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
|
||||||
|
*
|
||||||
|
* These are precondition-violations (user bugs) and internal errors (our bugs).
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API LogicError : public Exception {
|
||||||
|
public:
|
||||||
|
LogicError(String const& msg);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwRuntimeError(String const& msg);
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwLogicError(String const& msg);
|
||||||
|
|
||||||
|
/** \brief Type of the value held by a Value object.
|
||||||
|
*/
|
||||||
|
enum ValueType {
|
||||||
|
nullValue = 0, ///< 'null' value
|
||||||
|
intValue, ///< signed integer value
|
||||||
|
uintValue, ///< unsigned integer value
|
||||||
|
realValue, ///< double value
|
||||||
|
stringValue, ///< UTF-8 string value
|
||||||
|
booleanValue, ///< bool value
|
||||||
|
arrayValue, ///< array value (ordered list)
|
||||||
|
objectValue ///< object value (collection of name/value pairs).
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CommentPlacement {
|
||||||
|
commentBefore = 0, ///< a comment placed on the line before a value
|
||||||
|
commentAfterOnSameLine, ///< a comment just after a value on the same line
|
||||||
|
commentAfter, ///< a comment on the line after a value (only make sense for
|
||||||
|
/// root value)
|
||||||
|
numberOfCommentPlacement
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Type of precision for formatting of real values.
|
||||||
|
*/
|
||||||
|
enum PrecisionType {
|
||||||
|
significantDigits = 0, ///< we set max number of significant digits in string
|
||||||
|
decimalPlaces ///< we set max number of digits after "." in string
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Lightweight wrapper to tag static string.
|
||||||
|
*
|
||||||
|
* Value constructor and objectValue member assignment takes advantage of the
|
||||||
|
* StaticString and avoid the cost of string duplication when storing the
|
||||||
|
* string or the member name.
|
||||||
|
*
|
||||||
|
* Example of usage:
|
||||||
|
* \code
|
||||||
|
* Json::Value aValue( StaticString("some text") );
|
||||||
|
* Json::Value object;
|
||||||
|
* static const StaticString code("code");
|
||||||
|
* object[code] = 1234;
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StaticString {
|
||||||
|
public:
|
||||||
|
explicit StaticString(const char* czstring) : c_str_(czstring) {}
|
||||||
|
|
||||||
|
operator const char*() const { return c_str_; }
|
||||||
|
|
||||||
|
const char* c_str() const { return c_str_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* c_str_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
|
||||||
|
*
|
||||||
|
* This class is a discriminated union wrapper that can represents a:
|
||||||
|
* - signed integer [range: Value::minInt - Value::maxInt]
|
||||||
|
* - unsigned integer (range: 0 - Value::maxUInt)
|
||||||
|
* - double
|
||||||
|
* - UTF-8 string
|
||||||
|
* - boolean
|
||||||
|
* - 'null'
|
||||||
|
* - an ordered list of Value
|
||||||
|
* - collection of name/value pairs (javascript object)
|
||||||
|
*
|
||||||
|
* The type of the held value is represented by a #ValueType and
|
||||||
|
* can be obtained using type().
|
||||||
|
*
|
||||||
|
* Values of an #objectValue or #arrayValue can be accessed using operator[]()
|
||||||
|
* methods.
|
||||||
|
* Non-const methods will automatically create the a #nullValue element
|
||||||
|
* if it does not exist.
|
||||||
|
* The sequence of an #arrayValue will be automatically resized and initialized
|
||||||
|
* with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
|
||||||
|
*
|
||||||
|
* The get() methods can be used to obtain default value in the case the
|
||||||
|
* required element does not exist.
|
||||||
|
*
|
||||||
|
* It is possible to iterate over the list of member keys of an object using
|
||||||
|
* the getMemberNames() method.
|
||||||
|
*
|
||||||
|
* \note #Value string-length fit in size_t, but keys must be < 2^30.
|
||||||
|
* (The reason is an implementation detail.) A #CharReader will raise an
|
||||||
|
* exception if a bound is exceeded to avoid security holes in your app,
|
||||||
|
* but the Value API does *not* check bounds. That is the responsibility
|
||||||
|
* of the caller.
|
||||||
|
*/
|
||||||
|
class JSON_API Value {
|
||||||
|
friend class ValueIteratorBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Members = std::vector<String>;
|
||||||
|
using iterator = ValueIterator;
|
||||||
|
using const_iterator = ValueConstIterator;
|
||||||
|
using UInt = Json::UInt;
|
||||||
|
using Int = Json::Int;
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
using UInt64 = Json::UInt64;
|
||||||
|
using Int64 = Json::Int64;
|
||||||
|
#endif // defined(JSON_HAS_INT64)
|
||||||
|
using LargestInt = Json::LargestInt;
|
||||||
|
using LargestUInt = Json::LargestUInt;
|
||||||
|
using ArrayIndex = Json::ArrayIndex;
|
||||||
|
|
||||||
|
// Required for boost integration, e. g. BOOST_TEST
|
||||||
|
using value_type = std::string;
|
||||||
|
|
||||||
|
#if JSON_USE_NULLREF
|
||||||
|
// Binary compatibility kludges, do not use.
|
||||||
|
static const Value& null;
|
||||||
|
static const Value& nullRef;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// null and nullRef are deprecated, use this instead.
|
||||||
|
static Value const& nullSingleton();
|
||||||
|
|
||||||
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
|
static constexpr LargestInt minLargestInt =
|
||||||
|
LargestInt(~(LargestUInt(-1) / 2));
|
||||||
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
|
static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
|
||||||
|
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
||||||
|
static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
|
||||||
|
|
||||||
|
/// Minimum signed int value that can be stored in a Json::Value.
|
||||||
|
static constexpr Int minInt = Int(~(UInt(-1) / 2));
|
||||||
|
/// Maximum signed int value that can be stored in a Json::Value.
|
||||||
|
static constexpr Int maxInt = Int(UInt(-1) / 2);
|
||||||
|
/// Maximum unsigned int value that can be stored in a Json::Value.
|
||||||
|
static constexpr UInt maxUInt = UInt(-1);
|
||||||
|
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
||||||
|
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
||||||
|
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
||||||
|
static constexpr UInt64 maxUInt64 = UInt64(-1);
|
||||||
|
#endif // defined(JSON_HAS_INT64)
|
||||||
|
/// Default precision for real value for string representation.
|
||||||
|
static constexpr UInt defaultRealPrecision = 17;
|
||||||
|
// The constant is hard-coded because some compiler have trouble
|
||||||
|
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
|
||||||
|
// Assumes that UInt64 is a 64 bits integer.
|
||||||
|
static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
|
||||||
|
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
|
||||||
|
// when using gcc and clang backend compilers. CZString
|
||||||
|
// cannot be defined as private. See issue #486
|
||||||
|
#ifdef __NVCC__
|
||||||
|
public:
|
||||||
|
#else
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
class CZString {
|
||||||
|
public:
|
||||||
|
enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy };
|
||||||
|
CZString(ArrayIndex index);
|
||||||
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
|
CZString(CZString const& other);
|
||||||
|
CZString(CZString&& other) noexcept;
|
||||||
|
~CZString();
|
||||||
|
CZString& operator=(const CZString& other);
|
||||||
|
CZString& operator=(CZString&& other) noexcept;
|
||||||
|
|
||||||
|
bool operator<(CZString const& other) const;
|
||||||
|
bool operator==(CZString const& other) const;
|
||||||
|
ArrayIndex index() const;
|
||||||
|
// const char* c_str() const; ///< \deprecated
|
||||||
|
char const* data() const;
|
||||||
|
unsigned length() const;
|
||||||
|
bool isStaticString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void swap(CZString& other);
|
||||||
|
|
||||||
|
struct StringStorage {
|
||||||
|
unsigned policy_ : 2;
|
||||||
|
unsigned length_ : 30; // 1GB max
|
||||||
|
};
|
||||||
|
|
||||||
|
char const* cstr_; // actually, a prefixed string, unless policy is noDup
|
||||||
|
union {
|
||||||
|
ArrayIndex index_;
|
||||||
|
StringStorage storage_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef std::map<CZString, Value> ObjectValues;
|
||||||
|
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Create a default Value of the given type.
|
||||||
|
*
|
||||||
|
* This is a very useful constructor.
|
||||||
|
* To create an empty array, pass arrayValue.
|
||||||
|
* To create an empty object, pass objectValue.
|
||||||
|
* Another Value can then be set to this one by assignment.
|
||||||
|
* This is useful since clear() and resize() will not alter types.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* \code
|
||||||
|
* Json::Value null_value; // null
|
||||||
|
* Json::Value arr_value(Json::arrayValue); // []
|
||||||
|
* Json::Value obj_value(Json::objectValue); // {}
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
Value(ValueType type = nullValue);
|
||||||
|
Value(Int value);
|
||||||
|
Value(UInt value);
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
Value(Int64 value);
|
||||||
|
Value(UInt64 value);
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
Value(double value);
|
||||||
|
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
|
||||||
|
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
|
||||||
|
/**
|
||||||
|
* \brief Constructs a value from a static string.
|
||||||
|
*
|
||||||
|
* Like other value string constructor but do not duplicate the string for
|
||||||
|
* internal storage. The given string must remain alive after the call to
|
||||||
|
* this constructor.
|
||||||
|
*
|
||||||
|
* \note This works only for null-terminated strings. (We cannot change the
|
||||||
|
* size of this class, so we have nowhere to store the length, which might be
|
||||||
|
* computed later for various operations.)
|
||||||
|
*
|
||||||
|
* Example of usage:
|
||||||
|
* \code
|
||||||
|
* static StaticString foo("some text");
|
||||||
|
* Json::Value aValue(foo);
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
Value(const StaticString& value);
|
||||||
|
Value(const String& value);
|
||||||
|
Value(bool value);
|
||||||
|
Value(std::nullptr_t ptr) = delete;
|
||||||
|
Value(const Value& other);
|
||||||
|
Value(Value&& other) noexcept;
|
||||||
|
~Value();
|
||||||
|
|
||||||
|
/// \note Overwrite existing comments. To preserve comments, use
|
||||||
|
/// #swapPayload().
|
||||||
|
Value& operator=(const Value& other);
|
||||||
|
Value& operator=(Value&& other) noexcept;
|
||||||
|
|
||||||
|
/// Swap everything.
|
||||||
|
void swap(Value& other);
|
||||||
|
/// Swap values but leave comments and source offsets in place.
|
||||||
|
void swapPayload(Value& other);
|
||||||
|
|
||||||
|
/// copy everything.
|
||||||
|
void copy(const Value& other);
|
||||||
|
/// copy values but leave comments and source offsets in place.
|
||||||
|
void copyPayload(const Value& other);
|
||||||
|
|
||||||
|
ValueType type() const;
|
||||||
|
|
||||||
|
/// Compare payload only, not comments etc.
|
||||||
|
bool operator<(const Value& other) const;
|
||||||
|
bool operator<=(const Value& other) const;
|
||||||
|
bool operator>=(const Value& other) const;
|
||||||
|
bool operator>(const Value& other) const;
|
||||||
|
bool operator==(const Value& other) const;
|
||||||
|
bool operator!=(const Value& other) const;
|
||||||
|
int compare(const Value& other) const;
|
||||||
|
|
||||||
|
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
unsigned getCStringLength() const; // Allows you to understand the length of
|
||||||
|
// the CString
|
||||||
|
#endif
|
||||||
|
String asString() const; ///< Embedded zeroes are possible.
|
||||||
|
/** Get raw char* of string-value.
|
||||||
|
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||||
|
*/
|
||||||
|
bool getString(char const** begin, char const** end) const;
|
||||||
|
Int asInt() const;
|
||||||
|
UInt asUInt() const;
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
Int64 asInt64() const;
|
||||||
|
UInt64 asUInt64() const;
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
LargestInt asLargestInt() const;
|
||||||
|
LargestUInt asLargestUInt() const;
|
||||||
|
float asFloat() const;
|
||||||
|
double asDouble() const;
|
||||||
|
bool asBool() const;
|
||||||
|
|
||||||
|
bool isNull() const;
|
||||||
|
bool isBool() const;
|
||||||
|
bool isInt() const;
|
||||||
|
bool isInt64() const;
|
||||||
|
bool isUInt() const;
|
||||||
|
bool isUInt64() const;
|
||||||
|
bool isIntegral() const;
|
||||||
|
bool isDouble() const;
|
||||||
|
bool isNumeric() const;
|
||||||
|
bool isString() const;
|
||||||
|
bool isArray() const;
|
||||||
|
bool isObject() const;
|
||||||
|
|
||||||
|
/// The `as<T>` and `is<T>` member function templates and specializations.
|
||||||
|
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
|
||||||
|
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
|
||||||
|
|
||||||
|
bool isConvertibleTo(ValueType other) const;
|
||||||
|
|
||||||
|
/// Number of values in array or object
|
||||||
|
ArrayIndex size() const;
|
||||||
|
|
||||||
|
/// \brief Return true if empty array, empty object, or null;
|
||||||
|
/// otherwise, false.
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
/// Return !isNull()
|
||||||
|
explicit operator bool() const;
|
||||||
|
|
||||||
|
/// Remove all object members and array elements.
|
||||||
|
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||||
|
/// \post type() is unchanged
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Resize the array to newSize elements.
|
||||||
|
/// New elements are initialized to null.
|
||||||
|
/// May only be called on nullValue or arrayValue.
|
||||||
|
/// \pre type() is arrayValue or nullValue
|
||||||
|
/// \post type() is arrayValue
|
||||||
|
void resize(ArrayIndex newSize);
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Access an array element (zero based index). If the array contains less
|
||||||
|
/// than index element, then null value are inserted in the array so that
|
||||||
|
/// its size is index+1.
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
Value& operator[](ArrayIndex index);
|
||||||
|
Value& operator[](int index);
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Access an array element (zero based index).
|
||||||
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
|
/// this from the operator[] which takes a string.)
|
||||||
|
const Value& operator[](ArrayIndex index) const;
|
||||||
|
const Value& operator[](int index) const;
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/// If the array contains at least index+1 elements, returns the element
|
||||||
|
/// value, otherwise returns defaultValue.
|
||||||
|
Value get(ArrayIndex index, const Value& defaultValue) const;
|
||||||
|
/// Return true if index < size().
|
||||||
|
bool isValidIndex(ArrayIndex index) const;
|
||||||
|
/// \brief Append value to array at the end.
|
||||||
|
///
|
||||||
|
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||||
|
Value& append(const Value& value);
|
||||||
|
Value& append(Value&& value);
|
||||||
|
|
||||||
|
/// \brief Insert value in array at specific index
|
||||||
|
bool insert(ArrayIndex index, const Value& newValue);
|
||||||
|
bool insert(ArrayIndex index, Value&& newValue);
|
||||||
|
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
|
/// Exceeding that will cause an exception.
|
||||||
|
Value& operator[](const char* key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
const Value& operator[](const char* key) const;
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value& operator[](const String& key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
const Value& operator[](const String& key) const;
|
||||||
|
/** \brief Access an object value by name, create a null member if it does not
|
||||||
|
* exist.
|
||||||
|
*
|
||||||
|
* If the object has no entry for that name, then the member name used to
|
||||||
|
* store the new entry is not duplicated.
|
||||||
|
* Example of use:
|
||||||
|
* \code
|
||||||
|
* Json::Value object;
|
||||||
|
* static const StaticString code("code");
|
||||||
|
* object[code] = 1234;
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
Value& operator[](const StaticString& key);
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
/// \note key may contain embedded nulls.
|
||||||
|
Value get(const char* begin, const char* end,
|
||||||
|
const Value& defaultValue) const;
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value get(const String& key, const Value& defaultValue) const;
|
||||||
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
|
/// and operator[]const
|
||||||
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
|
Value const* find(char const* begin, char const* end) const;
|
||||||
|
/// Most general and efficient version of object-mutators.
|
||||||
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
|
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
||||||
|
Value* demand(char const* begin, char const* end);
|
||||||
|
/// \brief Remove and return the named member.
|
||||||
|
///
|
||||||
|
/// Do nothing if it did not exist.
|
||||||
|
/// \pre type() is objectValue or nullValue
|
||||||
|
/// \post type() is unchanged
|
||||||
|
void removeMember(const char* key);
|
||||||
|
/// Same as removeMember(const char*)
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
void removeMember(const String& key);
|
||||||
|
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||||
|
/// but 'key' is null-terminated.
|
||||||
|
bool removeMember(const char* key, Value* removed);
|
||||||
|
/** \brief Remove the named map member.
|
||||||
|
*
|
||||||
|
* Update 'removed' iff removed.
|
||||||
|
* \param key may contain embedded nulls.
|
||||||
|
* \return true iff removed (no exceptions)
|
||||||
|
*/
|
||||||
|
bool removeMember(String const& key, Value* removed);
|
||||||
|
/// Same as removeMember(String const& key, Value* removed)
|
||||||
|
bool removeMember(const char* begin, const char* end, Value* removed);
|
||||||
|
/** \brief Remove the indexed array element.
|
||||||
|
*
|
||||||
|
* O(n) expensive operations.
|
||||||
|
* Update 'removed' iff removed.
|
||||||
|
* \return true if removed (no exceptions)
|
||||||
|
*/
|
||||||
|
bool removeIndex(ArrayIndex index, Value* removed);
|
||||||
|
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
/// \note 'key' must be null-terminated.
|
||||||
|
bool isMember(const char* key) const;
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
bool isMember(const String& key) const;
|
||||||
|
/// Same as isMember(String const& key)const
|
||||||
|
bool isMember(const char* begin, const char* end) const;
|
||||||
|
|
||||||
|
/// \brief Return a list of the member names.
|
||||||
|
///
|
||||||
|
/// If null, return an empty list.
|
||||||
|
/// \pre type() is objectValue or nullValue
|
||||||
|
/// \post if type() was nullValue, it remains nullValue
|
||||||
|
Members getMemberNames() const;
|
||||||
|
|
||||||
|
/// \deprecated Always pass len.
|
||||||
|
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
||||||
|
void setComment(const char* comment, CommentPlacement placement) {
|
||||||
|
setComment(String(comment, strlen(comment)), placement);
|
||||||
|
}
|
||||||
|
/// Comments must be //... or /* ... */
|
||||||
|
void setComment(const char* comment, size_t len, CommentPlacement placement) {
|
||||||
|
setComment(String(comment, len), placement);
|
||||||
|
}
|
||||||
|
/// Comments must be //... or /* ... */
|
||||||
|
void setComment(String comment, CommentPlacement placement);
|
||||||
|
bool hasComment(CommentPlacement placement) const;
|
||||||
|
/// Include delimiters and embedded newlines.
|
||||||
|
String getComment(CommentPlacement placement) const;
|
||||||
|
|
||||||
|
String toStyledString() const;
|
||||||
|
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
iterator begin();
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
// Accessors for the [start, limit) range of bytes within the JSON text from
|
||||||
|
// which this value was parsed, if any.
|
||||||
|
void setOffsetStart(ptrdiff_t start);
|
||||||
|
void setOffsetLimit(ptrdiff_t limit);
|
||||||
|
ptrdiff_t getOffsetStart() const;
|
||||||
|
ptrdiff_t getOffsetLimit() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setType(ValueType v) {
|
||||||
|
bits_.value_type_ = static_cast<unsigned char>(v);
|
||||||
|
}
|
||||||
|
bool isAllocated() const { return bits_.allocated_; }
|
||||||
|
void setIsAllocated(bool v) { bits_.allocated_ = v; }
|
||||||
|
|
||||||
|
void initBasic(ValueType type, bool allocated = false);
|
||||||
|
void dupPayload(const Value& other);
|
||||||
|
void releasePayload();
|
||||||
|
void dupMeta(const Value& other);
|
||||||
|
|
||||||
|
Value& resolveReference(const char* key);
|
||||||
|
Value& resolveReference(const char* key, const char* end);
|
||||||
|
|
||||||
|
// struct MemberNamesTransform
|
||||||
|
//{
|
||||||
|
// typedef const char *result_type;
|
||||||
|
// const char *operator()( const CZString &name ) const
|
||||||
|
// {
|
||||||
|
// return name.c_str();
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
|
||||||
|
union ValueHolder {
|
||||||
|
LargestInt int_;
|
||||||
|
LargestUInt uint_;
|
||||||
|
double real_;
|
||||||
|
bool bool_;
|
||||||
|
char* string_; // if allocated_, ptr to { unsigned, char[] }.
|
||||||
|
ObjectValues* map_;
|
||||||
|
} value_;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
// Really a ValueType, but types should agree for bitfield packing.
|
||||||
|
unsigned int value_type_ : 8;
|
||||||
|
// Unless allocated_, string_ must be null-terminated.
|
||||||
|
unsigned int allocated_ : 1;
|
||||||
|
} bits_;
|
||||||
|
|
||||||
|
class Comments {
|
||||||
|
public:
|
||||||
|
Comments() = default;
|
||||||
|
Comments(const Comments& that);
|
||||||
|
Comments(Comments&& that) noexcept;
|
||||||
|
Comments& operator=(const Comments& that);
|
||||||
|
Comments& operator=(Comments&& that) noexcept;
|
||||||
|
bool has(CommentPlacement slot) const;
|
||||||
|
String get(CommentPlacement slot) const;
|
||||||
|
void set(CommentPlacement slot, String comment);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using Array = std::array<String, numberOfCommentPlacement>;
|
||||||
|
std::unique_ptr<Array> ptr_;
|
||||||
|
};
|
||||||
|
Comments comments_;
|
||||||
|
|
||||||
|
// [start, limit) byte offsets in the source JSON text from which this Value
|
||||||
|
// was extracted.
|
||||||
|
ptrdiff_t start_;
|
||||||
|
ptrdiff_t limit_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> inline bool Value::as<bool>() const { return asBool(); }
|
||||||
|
template <> inline bool Value::is<bool>() const { return isBool(); }
|
||||||
|
|
||||||
|
template <> inline Int Value::as<Int>() const { return asInt(); }
|
||||||
|
template <> inline bool Value::is<Int>() const { return isInt(); }
|
||||||
|
|
||||||
|
template <> inline UInt Value::as<UInt>() const { return asUInt(); }
|
||||||
|
template <> inline bool Value::is<UInt>() const { return isUInt(); }
|
||||||
|
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
|
||||||
|
template <> inline bool Value::is<Int64>() const { return isInt64(); }
|
||||||
|
|
||||||
|
template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
|
||||||
|
template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <> inline double Value::as<double>() const { return asDouble(); }
|
||||||
|
template <> inline bool Value::is<double>() const { return isDouble(); }
|
||||||
|
|
||||||
|
template <> inline String Value::as<String>() const { return asString(); }
|
||||||
|
template <> inline bool Value::is<String>() const { return isString(); }
|
||||||
|
|
||||||
|
/// These `as` specializations are type conversions, and do not have a
|
||||||
|
/// corresponding `is`.
|
||||||
|
template <> inline float Value::as<float>() const { return asFloat(); }
|
||||||
|
template <> inline const char* Value::as<const char*>() const {
|
||||||
|
return asCString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Experimental and untested: represents an element of the "path" to
|
||||||
|
* access a node.
|
||||||
|
*/
|
||||||
|
class JSON_API PathArgument {
|
||||||
|
public:
|
||||||
|
friend class Path;
|
||||||
|
|
||||||
|
PathArgument();
|
||||||
|
PathArgument(ArrayIndex index);
|
||||||
|
PathArgument(const char* key);
|
||||||
|
PathArgument(String key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Kind { kindNone = 0, kindIndex, kindKey };
|
||||||
|
String key_;
|
||||||
|
ArrayIndex index_{};
|
||||||
|
Kind kind_{kindNone};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Experimental and untested: represents a "path" to access a node.
|
||||||
|
*
|
||||||
|
* Syntax:
|
||||||
|
* - "." => root node
|
||||||
|
* - ".[n]" => elements at index 'n' of root node (an array value)
|
||||||
|
* - ".name" => member named 'name' of root node (an object value)
|
||||||
|
* - ".name1.name2.name3"
|
||||||
|
* - ".[0][1][2].name1[3]"
|
||||||
|
* - ".%" => member name is provided as parameter
|
||||||
|
* - ".[%]" => index is provided as parameter
|
||||||
|
*/
|
||||||
|
class JSON_API Path {
|
||||||
|
public:
|
||||||
|
Path(const String& path, const PathArgument& a1 = PathArgument(),
|
||||||
|
const PathArgument& a2 = PathArgument(),
|
||||||
|
const PathArgument& a3 = PathArgument(),
|
||||||
|
const PathArgument& a4 = PathArgument(),
|
||||||
|
const PathArgument& a5 = PathArgument());
|
||||||
|
|
||||||
|
const Value& resolve(const Value& root) const;
|
||||||
|
Value resolve(const Value& root, const Value& defaultValue) const;
|
||||||
|
/// Creates the "path" to access the specified node and returns a reference on
|
||||||
|
/// the node.
|
||||||
|
Value& make(Value& root) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using InArgs = std::vector<const PathArgument*>;
|
||||||
|
using Args = std::vector<PathArgument>;
|
||||||
|
|
||||||
|
void makePath(const String& path, const InArgs& in);
|
||||||
|
void addPathInArg(const String& path, const InArgs& in,
|
||||||
|
InArgs::const_iterator& itInArg, PathArgument::Kind kind);
|
||||||
|
static void invalidPath(const String& path, int location);
|
||||||
|
|
||||||
|
Args args_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief base class for Value iterators.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JSON_API ValueIteratorBase {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using size_t = unsigned int;
|
||||||
|
using difference_type = int;
|
||||||
|
using SelfType = ValueIteratorBase;
|
||||||
|
|
||||||
|
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||||
|
|
||||||
|
bool operator!=(const SelfType& other) const { return !isEqual(other); }
|
||||||
|
|
||||||
|
difference_type operator-(const SelfType& other) const {
|
||||||
|
return other.computeDistance(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return either the index or the member name of the referenced value as a
|
||||||
|
/// Value.
|
||||||
|
Value key() const;
|
||||||
|
|
||||||
|
/// Return the index of the referenced Value, or -1 if it is not an
|
||||||
|
/// arrayValue.
|
||||||
|
UInt index() const;
|
||||||
|
|
||||||
|
/// Return the member name of the referenced Value, or "" if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
|
||||||
|
String name() const;
|
||||||
|
|
||||||
|
/// Return the member name of the referenced Value. "" if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \deprecated This cannot be used for UTF-8 strings, since there can be
|
||||||
|
/// embedded nulls.
|
||||||
|
JSONCPP_DEPRECATED("Use `key = name();` instead.")
|
||||||
|
char const* memberName() const;
|
||||||
|
/// Return the member name of the referenced Value, or NULL if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \note Better version than memberName(). Allows embedded nulls.
|
||||||
|
char const* memberName(char const** end) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*! Internal utility functions to assist with implementing
|
||||||
|
* other iterator functions. The const and non-const versions
|
||||||
|
* of the "deref" protected methods expose the protected
|
||||||
|
* current_ member variable in a way that can often be
|
||||||
|
* optimized away by the compiler.
|
||||||
|
*/
|
||||||
|
const Value& deref() const;
|
||||||
|
Value& deref();
|
||||||
|
|
||||||
|
void increment();
|
||||||
|
|
||||||
|
void decrement();
|
||||||
|
|
||||||
|
difference_type computeDistance(const SelfType& other) const;
|
||||||
|
|
||||||
|
bool isEqual(const SelfType& other) const;
|
||||||
|
|
||||||
|
void copy(const SelfType& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Value::ObjectValues::iterator current_;
|
||||||
|
// Indicates that iterator is for a null value.
|
||||||
|
bool isNull_{true};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// For some reason, BORLAND needs these at the end, rather
|
||||||
|
// than earlier. No idea why.
|
||||||
|
ValueIteratorBase();
|
||||||
|
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief const iterator for object and array value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JSON_API ValueConstIterator : public ValueIteratorBase {
|
||||||
|
friend class Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = const Value;
|
||||||
|
// typedef unsigned int size_t;
|
||||||
|
// typedef int difference_type;
|
||||||
|
using reference = const Value&;
|
||||||
|
using pointer = const Value*;
|
||||||
|
using SelfType = ValueConstIterator;
|
||||||
|
|
||||||
|
ValueConstIterator();
|
||||||
|
ValueConstIterator(ValueIterator const& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*! \internal Use by Value to create an iterator.
|
||||||
|
*/
|
||||||
|
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SelfType& operator=(const ValueIteratorBase& other);
|
||||||
|
|
||||||
|
SelfType operator++(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
++*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType operator--(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
--*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator--() {
|
||||||
|
decrement();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator++() {
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const { return deref(); }
|
||||||
|
|
||||||
|
pointer operator->() const { return &deref(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Iterator for object and array value.
|
||||||
|
*/
|
||||||
|
class JSON_API ValueIterator : public ValueIteratorBase {
|
||||||
|
friend class Value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = Value;
|
||||||
|
using size_t = unsigned int;
|
||||||
|
using difference_type = int;
|
||||||
|
using reference = Value&;
|
||||||
|
using pointer = Value*;
|
||||||
|
using SelfType = ValueIterator;
|
||||||
|
|
||||||
|
ValueIterator();
|
||||||
|
explicit ValueIterator(const ValueConstIterator& other);
|
||||||
|
ValueIterator(const ValueIterator& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*! \internal Use by Value to create an iterator.
|
||||||
|
*/
|
||||||
|
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SelfType& operator=(const SelfType& other);
|
||||||
|
|
||||||
|
SelfType operator++(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
++*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType operator--(int) {
|
||||||
|
SelfType temp(*this);
|
||||||
|
--*this;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator--() {
|
||||||
|
decrement();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfType& operator++() {
|
||||||
|
increment();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! The return value of non-const iterators can be
|
||||||
|
* changed, so the these functions are not const
|
||||||
|
* because the returned references/pointers can be used
|
||||||
|
* to change state of the base class.
|
||||||
|
*/
|
||||||
|
reference operator*() const { return const_cast<reference>(deref()); }
|
||||||
|
pointer operator->() const { return const_cast<pointer>(&deref()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void swap(Value& a, Value& b) { a.swap(b); }
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // JSON_H_INCLUDED
|
||||||
28
thirdparty/openxr/src/external/jsoncpp/include/json/version.h
vendored
Normal file
28
thirdparty/openxr/src/external/jsoncpp/include/json/version.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
|
#define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
|
// Note: version must be updated in three places when doing a release. This
|
||||||
|
// annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
|
// correct version.
|
||||||
|
// 1. /meson.build
|
||||||
|
// 2. /include/json/version.h
|
||||||
|
// 3. /CMakeLists.txt
|
||||||
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
|
#define JSONCPP_VERSION_STRING "1.9.5"
|
||||||
|
#define JSONCPP_VERSION_MAJOR 1
|
||||||
|
#define JSONCPP_VERSION_MINOR 9
|
||||||
|
#define JSONCPP_VERSION_PATCH 5
|
||||||
|
#define JSONCPP_VERSION_QUALIFIER
|
||||||
|
#define JSONCPP_VERSION_HEXA \
|
||||||
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
|
(JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY 0
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
369
thirdparty/openxr/src/external/jsoncpp/include/json/writer.h
vendored
Normal file
369
thirdparty/openxr/src/external/jsoncpp/include/json/writer.h
vendored
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef JSON_WRITER_H_INCLUDED
|
||||||
|
#define JSON_WRITER_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include "value.h"
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* \code
|
||||||
|
* using namespace Json;
|
||||||
|
* void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
|
||||||
|
* { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
|
||||||
|
* writer->write(value, &std::cout);
|
||||||
|
* std::cout << std::endl; // add lf and flush
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriter {
|
||||||
|
protected:
|
||||||
|
OStream* sout_; // not owned; will not delete
|
||||||
|
public:
|
||||||
|
StreamWriter();
|
||||||
|
virtual ~StreamWriter();
|
||||||
|
/** Write Value into document as configured in sub-class.
|
||||||
|
* Do not take ownership of sout, but maintain a reference during function.
|
||||||
|
* \pre sout != NULL
|
||||||
|
* \return zero on success (For now, we always return zero, so check the
|
||||||
|
* stream instead.) \throw std::exception possibly, depending on
|
||||||
|
* configuration
|
||||||
|
*/
|
||||||
|
virtual int write(Value const& root, OStream* sout) = 0;
|
||||||
|
|
||||||
|
/** \brief A simple abstract factory.
|
||||||
|
*/
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory();
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual StreamWriter* newStreamWriter() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // StreamWriter
|
||||||
|
|
||||||
|
/** \brief Write into stringstream, then return string, for convenience.
|
||||||
|
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||||
|
*/
|
||||||
|
String JSON_API writeString(StreamWriter::Factory const& factory,
|
||||||
|
Value const& root);
|
||||||
|
|
||||||
|
/** \brief Build a StreamWriter implementation.
|
||||||
|
|
||||||
|
* Usage:
|
||||||
|
* \code
|
||||||
|
* using namespace Json;
|
||||||
|
* Value value = ...;
|
||||||
|
* StreamWriterBuilder builder;
|
||||||
|
* builder["commentStyle"] = "None";
|
||||||
|
* builder["indentation"] = " "; // or whatever you like
|
||||||
|
* std::unique_ptr<Json::StreamWriter> writer(
|
||||||
|
* builder.newStreamWriter());
|
||||||
|
* writer->write(value, &std::cout);
|
||||||
|
* std::cout << std::endl; // add lf and flush
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
* Available settings (case-sensitive):
|
||||||
|
* - "commentStyle": "None" or "All"
|
||||||
|
* - "indentation": "<anything>".
|
||||||
|
* - Setting this to an empty string also omits newline characters.
|
||||||
|
* - "enableYAMLCompatibility": false or true
|
||||||
|
* - slightly change the whitespace around colons
|
||||||
|
* - "dropNullPlaceholders": false or true
|
||||||
|
* - Drop the "null" string from the writer's output for nullValues.
|
||||||
|
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
|
* fed to a browser's JavaScript, it makes for smaller output and the
|
||||||
|
* browser can handle the output just fine.
|
||||||
|
* - "useSpecialFloats": false or true
|
||||||
|
* - If true, outputs non-finite floating point values in the following way:
|
||||||
|
* NaN values as "NaN", positive infinity as "Infinity", and negative
|
||||||
|
* infinity as "-Infinity".
|
||||||
|
* - "precision": int
|
||||||
|
* - Number of precision digits for formatting of real values.
|
||||||
|
* - "precisionType": "significant"(default) or "decimal"
|
||||||
|
* - Type of precision for formatting of real values.
|
||||||
|
* - "emitUTF8": false or true
|
||||||
|
* - If true, outputs raw UTF8 strings instead of escaping them.
|
||||||
|
|
||||||
|
* You can examine 'settings_` yourself
|
||||||
|
* to see the defaults. You can also write and read them just like any
|
||||||
|
* JSON Value.
|
||||||
|
* \sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
StreamWriterBuilder();
|
||||||
|
~StreamWriterBuilder() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
StreamWriter* newStreamWriter() const override;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](const String& key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Abstract class for writers.
|
||||||
|
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||||
|
*/
|
||||||
|
class JSON_API Writer {
|
||||||
|
public:
|
||||||
|
virtual ~Writer();
|
||||||
|
|
||||||
|
virtual String write(const Value& root) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||||
|
*without formatting (not human friendly).
|
||||||
|
*
|
||||||
|
* The JSON document is written in a single line. It is not intended for 'human'
|
||||||
|
*consumption,
|
||||||
|
* but may be useful to support feature such as RPC where bandwidth is limited.
|
||||||
|
* \sa Reader, Value
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
|
#endif
|
||||||
|
class JSON_API FastWriter
|
||||||
|
: public Writer {
|
||||||
|
public:
|
||||||
|
FastWriter();
|
||||||
|
~FastWriter() override = default;
|
||||||
|
|
||||||
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
|
/** \brief Drop the "null" string from the writer's output for nullValues.
|
||||||
|
* Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
|
* fed to a browser's JavaScript, it makes for smaller output and the
|
||||||
|
* browser can handle the output just fine.
|
||||||
|
*/
|
||||||
|
void dropNullPlaceholders();
|
||||||
|
|
||||||
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
|
public: // overridden from Writer
|
||||||
|
String write(const Value& root) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
|
String document_;
|
||||||
|
bool yamlCompatibilityEnabled_{false};
|
||||||
|
bool dropNullPlaceholders_{false};
|
||||||
|
bool omitEndingLineFeed_{false};
|
||||||
|
};
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
|
*human friendly way.
|
||||||
|
*
|
||||||
|
* The rules for line break and indent are as follow:
|
||||||
|
* - Object value:
|
||||||
|
* - if empty then print {} without indent and line break
|
||||||
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
|
*line
|
||||||
|
* and then unindent and line break and print '}'.
|
||||||
|
* - Array value:
|
||||||
|
* - if empty then print [] without indent and line break
|
||||||
|
* - if the array contains no object value, empty array or some other value
|
||||||
|
*types,
|
||||||
|
* and all the values fit on one lines, then print the array on a single
|
||||||
|
*line.
|
||||||
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
|
* object or non empty array, then print one value per line.
|
||||||
|
*
|
||||||
|
* If the Value have comments then they are outputed according to their
|
||||||
|
*#CommentPlacement.
|
||||||
|
*
|
||||||
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
|
#endif
|
||||||
|
class JSON_API
|
||||||
|
StyledWriter : public Writer {
|
||||||
|
public:
|
||||||
|
StyledWriter();
|
||||||
|
~StyledWriter() override = default;
|
||||||
|
|
||||||
|
public: // overridden from Writer
|
||||||
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
|
* \param root Value to serialize.
|
||||||
|
* \return String containing the JSON document that represents the root value.
|
||||||
|
*/
|
||||||
|
String write(const Value& root) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
void writeArrayValue(const Value& value);
|
||||||
|
bool isMultilineArray(const Value& value);
|
||||||
|
void pushValue(const String& value);
|
||||||
|
void writeIndent();
|
||||||
|
void writeWithIndent(const String& value);
|
||||||
|
void indent();
|
||||||
|
void unindent();
|
||||||
|
void writeCommentBeforeValue(const Value& root);
|
||||||
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
|
using ChildValues = std::vector<String>;
|
||||||
|
|
||||||
|
ChildValues childValues_;
|
||||||
|
String document_;
|
||||||
|
String indentString_;
|
||||||
|
unsigned int rightMargin_{74};
|
||||||
|
unsigned int indentSize_{3};
|
||||||
|
bool addChildValues_{false};
|
||||||
|
};
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
|
human friendly way,
|
||||||
|
to a stream rather than to a string.
|
||||||
|
*
|
||||||
|
* The rules for line break and indent are as follow:
|
||||||
|
* - Object value:
|
||||||
|
* - if empty then print {} without indent and line break
|
||||||
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
|
line
|
||||||
|
* and then unindent and line break and print '}'.
|
||||||
|
* - Array value:
|
||||||
|
* - if empty then print [] without indent and line break
|
||||||
|
* - if the array contains no object value, empty array or some other value
|
||||||
|
types,
|
||||||
|
* and all the values fit on one lines, then print the array on a single
|
||||||
|
line.
|
||||||
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
|
* object or non empty array, then print one value per line.
|
||||||
|
*
|
||||||
|
* If the Value have comments then they are outputed according to their
|
||||||
|
#CommentPlacement.
|
||||||
|
*
|
||||||
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
|
#endif
|
||||||
|
class JSON_API
|
||||||
|
StyledStreamWriter {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
|
*/
|
||||||
|
StyledStreamWriter(String indentation = "\t");
|
||||||
|
~StyledStreamWriter() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
|
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||||
|
* \param root Value to serialize.
|
||||||
|
* \note There is no point in deriving from Writer, since write() should not
|
||||||
|
* return a value.
|
||||||
|
*/
|
||||||
|
void write(OStream& out, const Value& root);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeValue(const Value& value);
|
||||||
|
void writeArrayValue(const Value& value);
|
||||||
|
bool isMultilineArray(const Value& value);
|
||||||
|
void pushValue(const String& value);
|
||||||
|
void writeIndent();
|
||||||
|
void writeWithIndent(const String& value);
|
||||||
|
void indent();
|
||||||
|
void unindent();
|
||||||
|
void writeCommentBeforeValue(const Value& root);
|
||||||
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
|
using ChildValues = std::vector<String>;
|
||||||
|
|
||||||
|
ChildValues childValues_;
|
||||||
|
OStream* document_;
|
||||||
|
String indentString_;
|
||||||
|
unsigned int rightMargin_{74};
|
||||||
|
String indentation_;
|
||||||
|
bool addChildValues_ : 1;
|
||||||
|
bool indented_ : 1;
|
||||||
|
};
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
|
String JSON_API valueToString(Int value);
|
||||||
|
String JSON_API valueToString(UInt value);
|
||||||
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
|
String JSON_API valueToString(LargestInt value);
|
||||||
|
String JSON_API valueToString(LargestUInt value);
|
||||||
|
String JSON_API valueToString(
|
||||||
|
double value, unsigned int precision = Value::defaultRealPrecision,
|
||||||
|
PrecisionType precisionType = PrecisionType::significantDigits);
|
||||||
|
String JSON_API valueToString(bool value);
|
||||||
|
String JSON_API valueToQuotedString(const char* value);
|
||||||
|
|
||||||
|
/// \brief Output using the StyledStreamWriter.
|
||||||
|
/// \see Json::operator>>()
|
||||||
|
JSON_API OStream& operator<<(OStream&, const Value& root);
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#endif // JSON_WRITER_H_INCLUDED
|
||||||
1992
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp
vendored
Normal file
1992
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
138
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h
vendored
Normal file
138
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h
vendored
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <json/config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Also support old flag NO_LOCALE_SUPPORT
|
||||||
|
#ifdef NO_LOCALE_SUPPORT
|
||||||
|
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#include <clocale>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This header provides common string manipulation support, such as UTF-8,
|
||||||
|
* portable conversion from/to string...
|
||||||
|
*
|
||||||
|
* It is an internal header that must not be exposed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
static inline char getDecimalPoint() {
|
||||||
|
#ifdef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
return '\0';
|
||||||
|
#else
|
||||||
|
struct lconv* lc = localeconv();
|
||||||
|
return lc ? *(lc->decimal_point) : '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a unicode code-point to UTF-8.
|
||||||
|
static inline String codePointToUTF8(unsigned int cp) {
|
||||||
|
String result;
|
||||||
|
|
||||||
|
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||||
|
|
||||||
|
if (cp <= 0x7f) {
|
||||||
|
result.resize(1);
|
||||||
|
result[0] = static_cast<char>(cp);
|
||||||
|
} else if (cp <= 0x7FF) {
|
||||||
|
result.resize(2);
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
||||||
|
} else if (cp <= 0xFFFF) {
|
||||||
|
result.resize(3);
|
||||||
|
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
|
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||||
|
} else if (cp <= 0x10FFFF) {
|
||||||
|
result.resize(4);
|
||||||
|
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
||||||
|
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/// Constant that specify the size of the buffer that must be passed to
|
||||||
|
/// uintToString.
|
||||||
|
uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defines a char buffer for use with uintToString().
|
||||||
|
using UIntToStringBuffer = char[uintToStringBufferSize];
|
||||||
|
|
||||||
|
/** Converts an unsigned integer to string.
|
||||||
|
* @param value Unsigned integer to convert to string
|
||||||
|
* @param current Input/Output string buffer.
|
||||||
|
* Must have at least uintToStringBufferSize chars free.
|
||||||
|
*/
|
||||||
|
static inline void uintToString(LargestUInt value, char*& current) {
|
||||||
|
*--current = 0;
|
||||||
|
do {
|
||||||
|
*--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
|
||||||
|
value /= 10;
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Change ',' to '.' everywhere in buffer.
|
||||||
|
*
|
||||||
|
* We had a sophisticated way, but it did not work in WinCE.
|
||||||
|
* @see https://github.com/open-source-parsers/jsoncpp/pull/9
|
||||||
|
*/
|
||||||
|
template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
if (*begin == ',') {
|
||||||
|
*begin = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
|
||||||
|
char decimalPoint = getDecimalPoint();
|
||||||
|
if (decimalPoint == '\0' || decimalPoint == '.') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
if (*begin == '.') {
|
||||||
|
*begin = decimalPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return iterator that would be the new end of the range [begin,end), if we
|
||||||
|
* were to delete zeros in the end of string, but not the last zero before '.'.
|
||||||
|
*/
|
||||||
|
template <typename Iter>
|
||||||
|
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
|
||||||
|
for (; begin != end; --end) {
|
||||||
|
if (*(end - 1) != '0') {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
// Don't delete the last zero before the decimal point.
|
||||||
|
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
|
||||||
|
if (precision) {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
return end - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
1634
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp
vendored
Normal file
1634
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
156
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl
vendored
Normal file
156
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
// included by json_value.cpp
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueIteratorBase
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueIteratorBase::ValueIteratorBase() : current_() {}
|
||||||
|
|
||||||
|
ValueIteratorBase::ValueIteratorBase(
|
||||||
|
const Value::ObjectValues::iterator& current)
|
||||||
|
: current_(current), isNull_(false) {}
|
||||||
|
|
||||||
|
Value& ValueIteratorBase::deref() { return current_->second; }
|
||||||
|
const Value& ValueIteratorBase::deref() const { return current_->second; }
|
||||||
|
|
||||||
|
void ValueIteratorBase::increment() { ++current_; }
|
||||||
|
|
||||||
|
void ValueIteratorBase::decrement() { --current_; }
|
||||||
|
|
||||||
|
ValueIteratorBase::difference_type
|
||||||
|
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
||||||
|
// Iterator for null value are initialized using the default
|
||||||
|
// constructor, which initialize current_ to the default
|
||||||
|
// std::map::iterator. As begin() and end() are two instance
|
||||||
|
// of the default std::map::iterator, they can not be compared.
|
||||||
|
// To allow this, we handle this comparison specifically.
|
||||||
|
if (isNull_ && other.isNull_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage of std::distance is not portable (does not compile with Sun Studio 12
|
||||||
|
// RogueWave STL,
|
||||||
|
// which is the one used by default).
|
||||||
|
// Using a portable hand-made version for non random iterator instead:
|
||||||
|
// return difference_type( std::distance( current_, other.current_ ) );
|
||||||
|
difference_type myDistance = 0;
|
||||||
|
for (Value::ObjectValues::iterator it = current_; it != other.current_;
|
||||||
|
++it) {
|
||||||
|
++myDistance;
|
||||||
|
}
|
||||||
|
return myDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||||
|
if (isNull_) {
|
||||||
|
return other.isNull_;
|
||||||
|
}
|
||||||
|
return current_ == other.current_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueIteratorBase::copy(const SelfType& other) {
|
||||||
|
current_ = other.current_;
|
||||||
|
isNull_ = other.isNull_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value ValueIteratorBase::key() const {
|
||||||
|
const Value::CZString czstring = (*current_).first;
|
||||||
|
if (czstring.data()) {
|
||||||
|
if (czstring.isStaticString())
|
||||||
|
return Value(StaticString(czstring.data()));
|
||||||
|
return Value(czstring.data(), czstring.data() + czstring.length());
|
||||||
|
}
|
||||||
|
return Value(czstring.index());
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt ValueIteratorBase::index() const {
|
||||||
|
const Value::CZString czstring = (*current_).first;
|
||||||
|
if (!czstring.data())
|
||||||
|
return czstring.index();
|
||||||
|
return Value::UInt(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String ValueIteratorBase::name() const {
|
||||||
|
char const* keey;
|
||||||
|
char const* end;
|
||||||
|
keey = memberName(&end);
|
||||||
|
if (!keey)
|
||||||
|
return String();
|
||||||
|
return String(keey, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ValueIteratorBase::memberName() const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
return cname ? cname : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
if (!cname) {
|
||||||
|
*end = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
*end = cname + (*current_).first.length();
|
||||||
|
return cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueConstIterator
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator() = default;
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator(
|
||||||
|
const Value::ObjectValues::iterator& current)
|
||||||
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
|
ValueConstIterator& ValueConstIterator::
|
||||||
|
operator=(const ValueIteratorBase& other) {
|
||||||
|
copy(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// class ValueIterator
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator() = default;
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||||
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||||
|
: ValueIteratorBase(other) {
|
||||||
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueIterator::ValueIterator(const ValueIterator& other) = default;
|
||||||
|
|
||||||
|
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||||
|
copy(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
1259
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp
vendored
Normal file
1259
thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
thirdparty/openxr/src/loader/.gitignore
vendored
Normal file
5
thirdparty/openxr/src/loader/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Copyright (c) 2020 The Khronos Group Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
!openxr_loader_for_android.pom
|
||||||
319
thirdparty/openxr/src/loader/android_utilities.cpp
vendored
Normal file
319
thirdparty/openxr/src/loader/android_utilities.cpp
vendored
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
// Copyright (c) 2020-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2020-2021, Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
|
||||||
|
#include "android_utilities.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <wrap/android.net.h>
|
||||||
|
#include <wrap/android.content.h>
|
||||||
|
#include <wrap/android.database.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "openxr_loader", __VA_ARGS__)
|
||||||
|
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, "openxr_loader", __VA_ARGS__)
|
||||||
|
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "openxr_loader", __VA_ARGS__)
|
||||||
|
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, "openxr_loader", __VA_ARGS__)
|
||||||
|
|
||||||
|
namespace openxr_android {
|
||||||
|
using wrap::android::content::ContentUris;
|
||||||
|
using wrap::android::content::Context;
|
||||||
|
using wrap::android::database::Cursor;
|
||||||
|
using wrap::android::net::Uri;
|
||||||
|
using wrap::android::net::Uri_Builder;
|
||||||
|
|
||||||
|
// Code in here corresponds roughly to the Java "BrokerContract" class and subclasses.
|
||||||
|
namespace {
|
||||||
|
constexpr auto AUTHORITY = "org.khronos.openxr.runtime_broker";
|
||||||
|
constexpr auto SYSTEM_AUTHORITY = "org.khronos.openxr.system_runtime_broker";
|
||||||
|
constexpr auto BASE_PATH = "openxr";
|
||||||
|
constexpr auto ABI_PATH = "abi";
|
||||||
|
constexpr auto RUNTIMES_PATH = "runtimes";
|
||||||
|
|
||||||
|
constexpr const char *getBrokerAuthority(bool systemBroker) { return systemBroker ? SYSTEM_AUTHORITY : AUTHORITY; }
|
||||||
|
|
||||||
|
struct BaseColumns {
|
||||||
|
/**
|
||||||
|
* The unique ID for a row.
|
||||||
|
*/
|
||||||
|
[[maybe_unused]] static constexpr auto ID = "_id";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains details for the /openxr/[major_ver]/abi/[abi]/runtimes/active URI.
|
||||||
|
* <p>
|
||||||
|
* This URI represents a "table" containing at most one item, the currently active runtime. The
|
||||||
|
* policy of which runtime is chosen to be active (if more than one is installed) is left to the
|
||||||
|
* content provider.
|
||||||
|
* <p>
|
||||||
|
* No sort order is required to be honored by the content provider.
|
||||||
|
*/
|
||||||
|
namespace active_runtime {
|
||||||
|
/**
|
||||||
|
* Final path component to this URI.
|
||||||
|
*/
|
||||||
|
static constexpr auto TABLE_PATH = "active";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a content URI for querying the data on the active runtime for a
|
||||||
|
* given major version of OpenXR.
|
||||||
|
*
|
||||||
|
* @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
|
||||||
|
* @param majorVer The major version of OpenXR.
|
||||||
|
* @param abi The Android ABI name in use.
|
||||||
|
* @return A content URI for a single item: the active runtime.
|
||||||
|
*/
|
||||||
|
static Uri makeContentUri(bool systemBroker, int majorVersion, const char *abi) {
|
||||||
|
auto builder = Uri_Builder::construct();
|
||||||
|
builder.scheme("content")
|
||||||
|
.authority(getBrokerAuthority(systemBroker))
|
||||||
|
.appendPath(BASE_PATH)
|
||||||
|
.appendPath(std::to_string(majorVersion))
|
||||||
|
.appendPath(ABI_PATH)
|
||||||
|
.appendPath(abi)
|
||||||
|
.appendPath(RUNTIMES_PATH)
|
||||||
|
.appendPath(TABLE_PATH);
|
||||||
|
ContentUris::appendId(builder, 0);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Columns : BaseColumns {
|
||||||
|
/**
|
||||||
|
* Constant for the PACKAGE_NAME column name
|
||||||
|
*/
|
||||||
|
static constexpr auto PACKAGE_NAME = "package_name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the NATIVE_LIB_DIR column name
|
||||||
|
*/
|
||||||
|
static constexpr auto NATIVE_LIB_DIR = "native_lib_dir";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the SO_FILENAME column name
|
||||||
|
*/
|
||||||
|
static constexpr auto SO_FILENAME = "so_filename";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the HAS_FUNCTIONS column name.
|
||||||
|
* <p>
|
||||||
|
* If this column contains true, you should check the /functions/ URI for that runtime.
|
||||||
|
*/
|
||||||
|
static constexpr auto HAS_FUNCTIONS = "has_functions";
|
||||||
|
};
|
||||||
|
} // namespace active_runtime
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains details for the /openxr/[major_ver]/abi/[abi]/runtimes/[package]/functions URI.
|
||||||
|
* <p>
|
||||||
|
* This URI is for package-specific function name remapping. Since this is an optional field in
|
||||||
|
* the corresponding JSON manifests for OpenXR, it is optional here as well. If the active
|
||||||
|
* runtime contains "true" in its "has_functions" column, then this table must exist and be
|
||||||
|
* queryable.
|
||||||
|
* <p>
|
||||||
|
* No sort order is required to be honored by the content provider.
|
||||||
|
*/
|
||||||
|
namespace functions {
|
||||||
|
/**
|
||||||
|
* Final path component to this URI.
|
||||||
|
*/
|
||||||
|
static constexpr auto TABLE_PATH = "functions";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a content URI for querying all rows of the function remapping data for a given
|
||||||
|
* runtime package and major version of OpenXR.
|
||||||
|
*
|
||||||
|
* @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
|
||||||
|
* @param majorVer The major version of OpenXR.
|
||||||
|
* @param packageName The package name of the runtime.
|
||||||
|
* @param abi The Android ABI name in use.
|
||||||
|
* @return A content URI for the entire table: the function remapping for that runtime.
|
||||||
|
*/
|
||||||
|
static Uri makeContentUri(bool systemBroker, int majorVersion, std::string const &packageName, const char *abi) {
|
||||||
|
auto builder = Uri_Builder::construct();
|
||||||
|
builder.scheme("content")
|
||||||
|
.authority(getBrokerAuthority(systemBroker))
|
||||||
|
.appendPath(BASE_PATH)
|
||||||
|
.appendPath(std::to_string(majorVersion))
|
||||||
|
.appendPath(ABI_PATH)
|
||||||
|
.appendPath(abi)
|
||||||
|
.appendPath(RUNTIMES_PATH)
|
||||||
|
.appendPath(packageName)
|
||||||
|
.appendPath(TABLE_PATH);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Columns : BaseColumns {
|
||||||
|
/**
|
||||||
|
* Constant for the FUNCTION_NAME column name
|
||||||
|
*/
|
||||||
|
static constexpr auto FUNCTION_NAME = "function_name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for the SYMBOL_NAME column name
|
||||||
|
*/
|
||||||
|
static constexpr auto SYMBOL_NAME = "symbol_name";
|
||||||
|
};
|
||||||
|
} // namespace functions
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static inline jni::Array<std::string> makeArray(std::initializer_list<const char *> &&list) {
|
||||||
|
auto ret = jni::Array<std::string>{(long)list.size()};
|
||||||
|
long i = 0;
|
||||||
|
for (auto &&elt : list) {
|
||||||
|
ret.setElement(i, elt);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static constexpr auto TAG = "OpenXR-Loader";
|
||||||
|
|
||||||
|
#if defined(__arm__)
|
||||||
|
static constexpr auto ABI = "armeabi-v7l";
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
static constexpr auto ABI = "arm64-v8a";
|
||||||
|
#elif defined(__i386__)
|
||||||
|
static constexpr auto ABI = "x86";
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
static constexpr auto ABI = "x86_64";
|
||||||
|
#else
|
||||||
|
#error "Unknown ABI!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Helper class to generate the jsoncpp object corresponding to a synthetic runtime manifest.
|
||||||
|
class JsonManifestBuilder {
|
||||||
|
public:
|
||||||
|
JsonManifestBuilder(const std::string &libraryPathParent, const std::string &libraryPath);
|
||||||
|
JsonManifestBuilder &function(const std::string &functionName, const std::string &symbolName);
|
||||||
|
|
||||||
|
Json::Value build() const { return root_node; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Json::Value root_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline JsonManifestBuilder::JsonManifestBuilder(const std::string &libraryPathParent, const std::string &libraryPath)
|
||||||
|
: root_node(Json::objectValue) {
|
||||||
|
root_node["file_format_version"] = "1.0.0";
|
||||||
|
root_node["instance_extensions"] = Json::Value(Json::arrayValue);
|
||||||
|
root_node["functions"] = Json::Value(Json::objectValue);
|
||||||
|
root_node[libraryPathParent] = Json::objectValue;
|
||||||
|
root_node[libraryPathParent]["library_path"] = libraryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonManifestBuilder &JsonManifestBuilder::function(const std::string &functionName, const std::string &symbolName) {
|
||||||
|
root_node["functions"][functionName] = symbolName;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr const char *getBrokerTypeName(bool systemBroker) { return systemBroker ? "system" : "installable"; }
|
||||||
|
|
||||||
|
static int populateFunctions(wrap::android::content::Context const &context, bool systemBroker, const std::string &packageName,
|
||||||
|
JsonManifestBuilder &builder) {
|
||||||
|
jni::Array<std::string> projection = makeArray({functions::Columns::FUNCTION_NAME, functions::Columns::SYMBOL_NAME});
|
||||||
|
|
||||||
|
auto uri = functions::makeContentUri(systemBroker, XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), packageName, ABI);
|
||||||
|
ALOGI("populateFunctions: Querying URI: %s", uri.toString().c_str());
|
||||||
|
|
||||||
|
Cursor cursor = context.getContentResolver().query(uri, projection);
|
||||||
|
|
||||||
|
if (cursor.isNull()) {
|
||||||
|
ALOGE("Null cursor when querying content resolver for functions.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (cursor.getCount() < 1) {
|
||||||
|
ALOGE("Non-null but empty cursor when querying content resolver for functions.");
|
||||||
|
cursor.close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto functionIndex = cursor.getColumnIndex(functions::Columns::FUNCTION_NAME);
|
||||||
|
auto symbolIndex = cursor.getColumnIndex(functions::Columns::SYMBOL_NAME);
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
builder.function(cursor.getString(functionIndex), cursor.getString(symbolIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get cursor for active runtime, parameterized by whether or not we use the system broker
|
||||||
|
static bool getActiveRuntimeCursor(wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
|
||||||
|
bool systemBroker, Cursor &cursor) {
|
||||||
|
auto uri = active_runtime::makeContentUri(systemBroker, XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), ABI);
|
||||||
|
ALOGI("getActiveRuntimeCursor: Querying URI: %s", uri.toString().c_str());
|
||||||
|
try {
|
||||||
|
cursor = context.getContentResolver().query(uri, projection);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
ALOGW("Exception when querying %s content resolver: %s", getBrokerTypeName(systemBroker), e.what());
|
||||||
|
cursor = {};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.isNull()) {
|
||||||
|
ALOGW("Null cursor when querying %s content resolver.", getBrokerTypeName(systemBroker));
|
||||||
|
cursor = {};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cursor.getCount() < 1) {
|
||||||
|
ALOGW("Non-null but empty cursor when querying %s content resolver.", getBrokerTypeName(systemBroker));
|
||||||
|
cursor.close();
|
||||||
|
cursor = {};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &context, Json::Value &virtualManifest) {
|
||||||
|
jni::Array<std::string> projection = makeArray({active_runtime::Columns::PACKAGE_NAME, active_runtime::Columns::NATIVE_LIB_DIR,
|
||||||
|
active_runtime::Columns::SO_FILENAME, active_runtime::Columns::HAS_FUNCTIONS});
|
||||||
|
|
||||||
|
// First, try getting the installable broker's provider
|
||||||
|
bool systemBroker = false;
|
||||||
|
Cursor cursor;
|
||||||
|
if (!getActiveRuntimeCursor(context, projection, systemBroker, cursor)) {
|
||||||
|
// OK, try the system broker as a fallback.
|
||||||
|
systemBroker = true;
|
||||||
|
getActiveRuntimeCursor(context, projection, systemBroker, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.isNull()) {
|
||||||
|
// Couldn't find either broker
|
||||||
|
ALOGE("Could access neither the installable nor system runtime broker.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.moveToFirst();
|
||||||
|
|
||||||
|
auto filename = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::SO_FILENAME));
|
||||||
|
auto libDir = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::NATIVE_LIB_DIR));
|
||||||
|
auto packageName = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::PACKAGE_NAME));
|
||||||
|
|
||||||
|
auto hasFunctions = cursor.getInt(cursor.getColumnIndex(active_runtime::Columns::HAS_FUNCTIONS)) == 1;
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, TAG, "Got runtime: package: %s, so filename: %s, native lib dir: %s, has functions: %s",
|
||||||
|
packageName.c_str(), libDir.c_str(), filename.c_str(), (hasFunctions ? "yes" : "no"));
|
||||||
|
|
||||||
|
auto lib_path = libDir + "/" + filename;
|
||||||
|
cursor.close();
|
||||||
|
|
||||||
|
JsonManifestBuilder builder{"runtime", lib_path};
|
||||||
|
if (hasFunctions) {
|
||||||
|
int result = populateFunctions(context, systemBroker, packageName, builder);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtualManifest = builder.build();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // namespace openxr_android
|
||||||
|
|
||||||
|
#endif // __ANDROID__
|
||||||
32
thirdparty/openxr/src/loader/android_utilities.h
vendored
Normal file
32
thirdparty/openxr/src/loader/android_utilities.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2020-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2020-2021, Collabora, Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
|
#include "wrap/android.content.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
namespace Json {
|
||||||
|
class Value;
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
namespace openxr_android {
|
||||||
|
using wrap::android::content::Context;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Find the single active OpenXR runtime on the system, and return a constructed JSON object representing it.
|
||||||
|
*
|
||||||
|
* @param context An Android context, preferably an Activity Context.
|
||||||
|
* @param[out] virtualManifest The Json::Value to fill with the virtual manifest.
|
||||||
|
*
|
||||||
|
* @return 0 on success, something else on failure.
|
||||||
|
*/
|
||||||
|
int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &context, Json::Value &virtualManifest);
|
||||||
|
} // namespace openxr_android
|
||||||
|
|
||||||
|
#endif // __ANDROID__
|
||||||
399
thirdparty/openxr/src/loader/api_layer_interface.cpp
vendored
Normal file
399
thirdparty/openxr/src/loader/api_layer_interface.cpp
vendored
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define OPENXR_ENABLE_LAYERS_ENV_VAR "XR_ENABLE_API_LAYERS"
|
||||||
|
|
||||||
|
// Add any layers defined in the loader layer environment variable.
|
||||||
|
static void AddEnvironmentApiLayers(std::vector<std::string>& enabled_layers) {
|
||||||
|
std::string layers = PlatformUtilsGetEnv(OPENXR_ENABLE_LAYERS_ENV_VAR);
|
||||||
|
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = layers.find_first_of(PATH_SEPARATOR);
|
||||||
|
std::string cur_search;
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
cur_search = layers.substr(last_found, found - last_found);
|
||||||
|
enabled_layers.push_back(cur_search);
|
||||||
|
last_found = found + 1;
|
||||||
|
found = layers.find_first_of(PATH_SEPARATOR, last_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
if (last_found < layers.size()) {
|
||||||
|
cur_search = layers.substr(last_found);
|
||||||
|
enabled_layers.push_back(cur_search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count,
|
||||||
|
uint32_t* outgoing_count, XrApiLayerProperties* api_layer_properties) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
|
||||||
|
uint32_t manifest_count = 0;
|
||||||
|
|
||||||
|
// Validate props struct before proceeding
|
||||||
|
if (0 < incoming_count && nullptr != api_layer_properties) {
|
||||||
|
for (uint32_t i = 0; i < incoming_count; i++) {
|
||||||
|
if (XR_TYPE_API_LAYER_PROPERTIES != api_layer_properties[i].type) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"VUID-XrApiLayerProperties-type-type: unknown type in api_layer_properties");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Independent of elementCapacityInput or elements parameters, elementCountOutput must be a valid pointer,
|
||||||
|
// and the function sets elementCountOutput." - 2.11
|
||||||
|
if (nullptr == outgoing_count) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find any implicit layers which we may need to report information for.
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
// Find any explicit layers which we may need to report information for.
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
|
||||||
|
}
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"ApiLayerInterface::GetApiLayerProperties - failed searching for API layer manifest files");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest_count = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
if (nullptr == outgoing_count) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
|
||||||
|
"VUID-xrEnumerateApiLayerProperties-propertyCountOutput-parameter: null propertyCountOutput");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outgoing_count = manifest_count;
|
||||||
|
if (0 == incoming_count) {
|
||||||
|
// capacity check only
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
if (nullptr == api_layer_properties) {
|
||||||
|
// incoming_count is not 0 BUT the api_layer_properties is NULL
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
|
||||||
|
"VUID-xrEnumerateApiLayerProperties-properties-parameter: non-zero capacity but null array");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
if (incoming_count < manifest_count) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrEnumerateInstanceExtensionProperties",
|
||||||
|
"VUID-xrEnumerateApiLayerProperties-propertyCapacityInput-parameter: insufficient space in array");
|
||||||
|
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t prop = 0; prop < incoming_count && prop < manifest_count; ++prop) {
|
||||||
|
manifest_files[prop]->PopulateApiLayerProperties(api_layer_properties[prop]);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
|
||||||
|
std::vector<XrExtensionProperties>& extension_properties) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
|
||||||
|
|
||||||
|
// If a layer name is supplied, only use the information out of that one layer
|
||||||
|
if (nullptr != layer_name && 0 != strlen(layer_name)) {
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
// Find any explicit layers which we may need to report information for.
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
openxr_command,
|
||||||
|
"ApiLayerInterface::GetInstanceExtensionProperties - failed searching for API layer manifest files");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
auto num_files = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
|
||||||
|
// If a layer with the provided name exists, get it's instance extension information.
|
||||||
|
if (manifest_files[man_file]->LayerName() == layer_name) {
|
||||||
|
manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing found, report 0
|
||||||
|
if (!found) {
|
||||||
|
return XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, we want to add only implicit API layers and explicit API layers enabled using the environment variables
|
||||||
|
} else {
|
||||||
|
XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
// Find any environmentally enabled explicit layers. If they're present, treat them like implicit layers
|
||||||
|
// since we know that they're going to be enabled.
|
||||||
|
std::vector<std::string> env_enabled_layers;
|
||||||
|
AddEnvironmentApiLayers(env_enabled_layers);
|
||||||
|
if (!env_enabled_layers.empty()) {
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> exp_layer_man_files = {};
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, exp_layer_man_files);
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
for (auto& exp_layer_man_file : exp_layer_man_files) {
|
||||||
|
for (std::string& enabled_layer : env_enabled_layers) {
|
||||||
|
// If this is an enabled layer, transfer it over to the manifest list.
|
||||||
|
if (enabled_layer == exp_layer_man_file->LayerName()) {
|
||||||
|
manifest_files.push_back(std::move(exp_layer_man_file));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the layer instance extensions information
|
||||||
|
auto num_files = static_cast<uint32_t>(manifest_files.size());
|
||||||
|
for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
|
||||||
|
manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
|
||||||
|
const char* const* enabled_api_layer_names,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces) {
|
||||||
|
XrResult last_error = XR_SUCCESS;
|
||||||
|
std::unordered_set<std::string> layers_already_found;
|
||||||
|
|
||||||
|
bool any_loaded = false;
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> enabled_layer_manifest_files_in_init_order = {};
|
||||||
|
|
||||||
|
// Find any implicit layers.
|
||||||
|
XrResult result =
|
||||||
|
ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, enabled_layer_manifest_files_in_init_order);
|
||||||
|
|
||||||
|
for (const auto& enabled_layer_manifest_file : enabled_layer_manifest_files_in_init_order) {
|
||||||
|
layers_already_found.insert(enabled_layer_manifest_file->LayerName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find any explicit layers.
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> explicit_layer_manifest_files = {};
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, explicit_layer_manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found_all_layers = true;
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
// Put all explicit and then xrCreateInstance enabled layers into a string vector
|
||||||
|
|
||||||
|
std::vector<std::string> enabled_explicit_api_layer_names = {};
|
||||||
|
|
||||||
|
AddEnvironmentApiLayers(enabled_explicit_api_layer_names);
|
||||||
|
|
||||||
|
if (enabled_api_layer_count > 0) {
|
||||||
|
if (nullptr == enabled_api_layer_names) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrCreateInstance",
|
||||||
|
"VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter: enabledApiLayerCount is non-0 but array is NULL");
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"xrCreateInstance", "VUID-xrCreateInstance-info-parameter: something wrong with XrInstanceCreateInfo contents");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(enabled_api_layer_names, enabled_api_layer_names + enabled_api_layer_count,
|
||||||
|
std::back_inserter(enabled_explicit_api_layer_names));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add explicit layers to list of layers to enable
|
||||||
|
for (const auto& layer_name : enabled_explicit_api_layer_names) {
|
||||||
|
bool found_this_layer = false;
|
||||||
|
|
||||||
|
for (auto it = explicit_layer_manifest_files.begin(); it != explicit_layer_manifest_files.end();) {
|
||||||
|
bool erased_layer_manifest_file = false;
|
||||||
|
|
||||||
|
if (layers_already_found.count(layer_name) > 0) {
|
||||||
|
found_this_layer = true;
|
||||||
|
} else if (layer_name == (*it)->LayerName()) {
|
||||||
|
found_this_layer = true;
|
||||||
|
layers_already_found.insert(layer_name);
|
||||||
|
enabled_layer_manifest_files_in_init_order.push_back(std::move(*it));
|
||||||
|
it = explicit_layer_manifest_files.erase(it);
|
||||||
|
erased_layer_manifest_file = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!erased_layer_manifest_file) {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If even one of the layers wasn't found, we want to return an error
|
||||||
|
if (!found_this_layer) {
|
||||||
|
found_all_layers = false;
|
||||||
|
std::string error_message = "ApiLayerInterface::LoadApiLayers - failed to find layer ";
|
||||||
|
error_message += layer_name;
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::unique_ptr<ApiLayerManifestFile>& manifest_file : enabled_layer_manifest_files_in_init_order) {
|
||||||
|
LoaderPlatformLibraryHandle layer_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
|
||||||
|
if (nullptr == layer_library) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
|
||||||
|
std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
|
||||||
|
warning_message += manifest_file->LayerName();
|
||||||
|
warning_message += ", failed to load with message \"";
|
||||||
|
warning_message += library_message;
|
||||||
|
warning_message += "\"";
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, warning_message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and settle on an layer interface version (using any provided name if required).
|
||||||
|
std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderApiLayerInterface");
|
||||||
|
auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderApiLayerInterface>(
|
||||||
|
LoaderPlatformLibraryGetProcAddr(layer_library, function_name));
|
||||||
|
|
||||||
|
if (nullptr == negotiate) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
|
||||||
|
<< " because negotiation function " << function_name << " was not found";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, oss.str());
|
||||||
|
LoaderPlatformLibraryClose(layer_library);
|
||||||
|
last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loader info for negotiation
|
||||||
|
XrNegotiateLoaderInfo loader_info = {};
|
||||||
|
loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
|
||||||
|
loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
|
||||||
|
loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
|
||||||
|
loader_info.minInterfaceVersion = 1;
|
||||||
|
loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
|
||||||
|
loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
|
||||||
|
loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
|
||||||
|
|
||||||
|
// Set up the layer return structure
|
||||||
|
XrNegotiateApiLayerRequest api_layer_info = {};
|
||||||
|
api_layer_info.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST;
|
||||||
|
api_layer_info.structVersion = XR_API_LAYER_INFO_STRUCT_VERSION;
|
||||||
|
api_layer_info.structSize = sizeof(XrNegotiateApiLayerRequest);
|
||||||
|
|
||||||
|
XrResult res = negotiate(&loader_info, manifest_file->LayerName().c_str(), &api_layer_info);
|
||||||
|
// If we supposedly succeeded, but got a nullptr for getInstanceProcAddr
|
||||||
|
// then something still went wrong, so return with an error.
|
||||||
|
if (XR_SUCCEEDED(res) && nullptr == api_layer_info.getInstanceProcAddr) {
|
||||||
|
std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
|
||||||
|
warning_message += manifest_file->LayerName();
|
||||||
|
warning_message += ", negotiation did not return a valid getInstanceProcAddr";
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, warning_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
}
|
||||||
|
if (XR_FAILED(res)) {
|
||||||
|
if (!any_loaded) {
|
||||||
|
last_error = res;
|
||||||
|
}
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
|
||||||
|
<< " due to failed negotiation with error " << res;
|
||||||
|
LoaderLogger::LogWarningMessage(openxr_command, oss.str());
|
||||||
|
LoaderPlatformLibraryClose(layer_library);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "ApiLayerInterface::LoadApiLayers succeeded loading layer " << manifest_file->LayerName()
|
||||||
|
<< " using interface version " << api_layer_info.layerInterfaceVersion << " and OpenXR API version "
|
||||||
|
<< XR_VERSION_MAJOR(api_layer_info.layerApiVersion) << "." << XR_VERSION_MINOR(api_layer_info.layerApiVersion);
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the list of extensions this layer supports for easy filtering after the
|
||||||
|
// xrCreateInstance call
|
||||||
|
std::vector<std::string> supported_extensions;
|
||||||
|
std::vector<XrExtensionProperties> extension_properties;
|
||||||
|
manifest_file->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
supported_extensions.reserve(extension_properties.size());
|
||||||
|
for (XrExtensionProperties& ext_prop : extension_properties) {
|
||||||
|
supported_extensions.emplace_back(ext_prop.extensionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this API layer to the vector
|
||||||
|
api_layer_interfaces.emplace_back(new ApiLayerInterface(manifest_file->LayerName(), layer_library, supported_extensions,
|
||||||
|
api_layer_info.getInstanceProcAddr,
|
||||||
|
api_layer_info.createApiLayerInstance));
|
||||||
|
|
||||||
|
// If we load one, clear all errors.
|
||||||
|
any_loaded = true;
|
||||||
|
last_error = XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set error here to preserve prior error behavior
|
||||||
|
if (!found_all_layers) {
|
||||||
|
last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we failed catastrophically for some reason, clean up everything.
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
api_layer_interfaces.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiLayerInterface::ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
|
||||||
|
std::vector<std::string>& supported_extensions,
|
||||||
|
PFN_xrGetInstanceProcAddr get_instance_proc_addr,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance)
|
||||||
|
: _layer_name(layer_name),
|
||||||
|
_layer_library(layer_library),
|
||||||
|
_get_instance_proc_addr(get_instance_proc_addr),
|
||||||
|
_create_api_layer_instance(create_api_layer_instance),
|
||||||
|
_supported_extensions(supported_extensions) {}
|
||||||
|
|
||||||
|
ApiLayerInterface::~ApiLayerInterface() {
|
||||||
|
std::string info_message = "ApiLayerInterface being destroyed for layer ";
|
||||||
|
info_message += _layer_name;
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
LoaderPlatformLibraryClose(_layer_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApiLayerInterface::SupportsExtension(const std::string& extension_name) const {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (const std::string& supported_extension : _supported_extensions) {
|
||||||
|
if (supported_extension == extension_name) {
|
||||||
|
found_prop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_prop;
|
||||||
|
}
|
||||||
54
thirdparty/openxr/src/loader/api_layer_interface.hpp
vendored
Normal file
54
thirdparty/openxr/src/loader/api_layer_interface.hpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
class ApiLayerInterface {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
|
||||||
|
const char* const* enabled_api_layer_names,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces);
|
||||||
|
// Static queries
|
||||||
|
static XrResult GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count, uint32_t* outgoing_count,
|
||||||
|
XrApiLayerProperties* api_layer_properties);
|
||||||
|
static XrResult GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
|
||||||
|
std::vector<XrExtensionProperties>& extension_properties);
|
||||||
|
|
||||||
|
ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
|
||||||
|
std::vector<std::string>& supported_extensions, PFN_xrGetInstanceProcAddr get_instance_proc_addr,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance);
|
||||||
|
virtual ~ApiLayerInterface();
|
||||||
|
|
||||||
|
PFN_xrGetInstanceProcAddr GetInstanceProcAddrFuncPointer() { return _get_instance_proc_addr; }
|
||||||
|
PFN_xrCreateApiLayerInstance GetCreateApiLayerInstanceFuncPointer() { return _create_api_layer_instance; }
|
||||||
|
|
||||||
|
std::string LayerName() { return _layer_name; }
|
||||||
|
|
||||||
|
// Generated methods
|
||||||
|
bool SupportsExtension(const std::string& extension_name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _layer_name;
|
||||||
|
LoaderPlatformLibraryHandle _layer_library;
|
||||||
|
PFN_xrGetInstanceProcAddr _get_instance_proc_addr;
|
||||||
|
PFN_xrCreateApiLayerInstance _create_api_layer_instance;
|
||||||
|
std::vector<std::string> _supported_extensions;
|
||||||
|
};
|
||||||
40
thirdparty/openxr/src/loader/exception_handling.hpp
vendored
Normal file
40
thirdparty/openxr/src/loader/exception_handling.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2019-2022, The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
// Provides protection for C ABI functions if standard library functions may throw.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
#include "common_config.h"
|
||||||
|
#endif // OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
|
||||||
|
#ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING
|
||||||
|
|
||||||
|
#define XRLOADER_ABI_TRY
|
||||||
|
#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM
|
||||||
|
#define XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#define XRLOADER_ABI_TRY try
|
||||||
|
#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM \
|
||||||
|
catch (const std::bad_alloc&) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "failed allocating memory"); \
|
||||||
|
return XR_ERROR_OUT_OF_MEMORY; \
|
||||||
|
}
|
||||||
|
#define XRLOADER_ABI_CATCH_FALLBACK \
|
||||||
|
catch (const std::exception& e) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "Unknown failure: " + std::string(e.what())); \
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE; \
|
||||||
|
} \
|
||||||
|
catch (...) { \
|
||||||
|
LoaderLogger::LogErrorMessage("", "Unknown failure"); \
|
||||||
|
return XR_ERROR_RUNTIME_FAILURE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
847
thirdparty/openxr/src/loader/loader_core.cpp
vendored
Normal file
847
thirdparty/openxr/src/loader/loader_core.cpp
vendored
Normal file
@@ -0,0 +1,847 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
#include "exception_handling.hpp"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "xr_generated_loader.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Global loader lock to:
|
||||||
|
// 1. Ensure ActiveLoaderInstance get and set operations are done atomically.
|
||||||
|
// 2. Ensure RuntimeInterface isn't used to unload the runtime while the runtime is in use.
|
||||||
|
std::mutex &GetGlobalLoaderMutex() {
|
||||||
|
static std::mutex loader_mutex;
|
||||||
|
return loader_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prototypes for the debug utils calls used internally.
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineCreateDebugUtilsMessengerEXT(
|
||||||
|
XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo, XrDebugUtilsMessengerEXT *messenger);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
|
||||||
|
// Terminal functions needed by xrCreateInstance.
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance, const char *, PFN_xrVoidFunction *);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *, XrInstance *);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *,
|
||||||
|
const struct XrApiLayerCreateInfo *, XrInstance *);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance, const XrDebugUtilsObjectNameInfoEXT *);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *,
|
||||||
|
XrDebugUtilsMessengerEXT *);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT);
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT *callbackData);
|
||||||
|
|
||||||
|
// Utility template function meant to validate if a fixed size string contains
|
||||||
|
// a null-terminator.
|
||||||
|
template <size_t max_length>
|
||||||
|
inline bool IsMissingNullTerminator(const char (&str)[max_length]) {
|
||||||
|
for (size_t index = 0; index < max_length; ++index) {
|
||||||
|
if (str[index] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Core 1.0 manual loader trampoline functions
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT // platforms that support XR_KHR_loader_init.
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrInitializeLoaderKHR", "Entering loader trampoline");
|
||||||
|
return InitializeLoader(loaderInitInfo);
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
|
||||||
|
uint32_t *propertyCountOutput,
|
||||||
|
XrApiLayerProperties *properties) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
|
||||||
|
|
||||||
|
// Make sure only one thread is attempting to read the JSON files at a time.
|
||||||
|
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
|
||||||
|
|
||||||
|
XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
|
||||||
|
propertyCountOutput, properties);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderXrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput,
|
||||||
|
XrExtensionProperties *properties) XRLOADER_ABI_TRY {
|
||||||
|
bool just_layer_properties = false;
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline");
|
||||||
|
|
||||||
|
// "Independent of elementCapacityInput or elements parameters, elementCountOutput must be a valid pointer,
|
||||||
|
// and the function sets elementCountOutput." - 2.11
|
||||||
|
if (nullptr == propertyCountOutput) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != layerName && 0 != strlen(layerName)) {
|
||||||
|
// Application is only interested in layer's properties, not all of them.
|
||||||
|
just_layer_properties = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<XrExtensionProperties> extension_properties = {};
|
||||||
|
XrResult result;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Make sure the runtime isn't unloaded while this call is in progress.
|
||||||
|
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
|
||||||
|
|
||||||
|
// Get the layer extension properties
|
||||||
|
result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
|
||||||
|
extension_properties);
|
||||||
|
if (XR_SUCCEEDED(result) && !just_layer_properties) {
|
||||||
|
// If not specific to a layer, get the runtime extension properties
|
||||||
|
result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties);
|
||||||
|
} else {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
|
||||||
|
"Failed to find default runtime with RuntimeInterface::LoadRuntime()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is not in reference to a specific layer, then add the loader-specific extension properties as well.
|
||||||
|
// These are extensions that the loader directly supports.
|
||||||
|
if (!just_layer_properties) {
|
||||||
|
for (const XrExtensionProperties &loader_prop : LoaderInstance::LoaderSpecificExtensions()) {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (XrExtensionProperties &existing_prop : extension_properties) {
|
||||||
|
if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) {
|
||||||
|
found_prop = true;
|
||||||
|
// Use the loader version if it is newer
|
||||||
|
if (existing_prop.extensionVersion < loader_prop.extensionVersion) {
|
||||||
|
existing_prop.extensionVersion = loader_prop.extensionVersion;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only add extensions not supported by the loader
|
||||||
|
if (!found_prop) {
|
||||||
|
extension_properties.push_back(loader_prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto num_extension_properties = static_cast<uint32_t>(extension_properties.size());
|
||||||
|
if (propertyCapacityInput == 0) {
|
||||||
|
*propertyCountOutput = num_extension_properties;
|
||||||
|
} else if (nullptr != properties) {
|
||||||
|
if (propertyCapacityInput < num_extension_properties) {
|
||||||
|
*propertyCountOutput = num_extension_properties;
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "insufficient space in array");
|
||||||
|
return XR_ERROR_SIZE_INSUFFICIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t num_to_copy = num_extension_properties;
|
||||||
|
// Determine how many extension properties we can copy over
|
||||||
|
if (propertyCapacityInput < num_to_copy) {
|
||||||
|
num_to_copy = propertyCapacityInput;
|
||||||
|
}
|
||||||
|
bool properties_valid = true;
|
||||||
|
for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) {
|
||||||
|
if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) {
|
||||||
|
properties_valid = false;
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "unknown type in properties");
|
||||||
|
}
|
||||||
|
if (properties_valid) {
|
||||||
|
properties[prop] = extension_properties[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!properties_valid) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter",
|
||||||
|
"xrEnumerateInstanceExtensionProperties", "invalid properties");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
if (nullptr != propertyCountOutput) {
|
||||||
|
*propertyCountOutput = num_to_copy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// incoming_count is not 0 BUT the properties is NULL
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline");
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrCreateInstance(const XrInstanceCreateInfo *info,
|
||||||
|
XrInstance *instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline");
|
||||||
|
if (nullptr == info) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// If application requested OpenXR API version is higher than the loader version, then we need to throw
|
||||||
|
// an error.
|
||||||
|
uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT
|
||||||
|
uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT
|
||||||
|
uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT
|
||||||
|
uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT
|
||||||
|
if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor
|
||||||
|
<< ". Max supported version is " << loader_major << "." << loader_minor;
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str());
|
||||||
|
return XR_ERROR_API_VERSION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == instance) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the ActiveLoaderInstance::IsAvailable check is done atomically with RuntimeInterface::LoadRuntime.
|
||||||
|
std::unique_lock<std::mutex> instance_lock(GetGlobalLoaderMutex());
|
||||||
|
|
||||||
|
// Check if there is already an XrInstance that is alive. If so, another instance cannot be created.
|
||||||
|
// The loader does not support multiple simultaneous instances because the loader is intended to be
|
||||||
|
// usable by apps using future OpenXR APIs (through xrGetInstanceProcAddr). Because the loader would
|
||||||
|
// not be aware of new handle types, it would not be able to look up the appropriate dispatch table
|
||||||
|
// in some cases.
|
||||||
|
if (ActiveLoaderInstance::IsAvailable()) { // If there is an XrInstance already alive.
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "Loader does not support simultaneous XrInstances");
|
||||||
|
return XR_ERROR_LIMIT_REACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces;
|
||||||
|
XrResult result;
|
||||||
|
|
||||||
|
// Make sure only one thread is attempting to read the JSON files and use the instance.
|
||||||
|
{
|
||||||
|
// Load the available runtime
|
||||||
|
result = RuntimeInterface::LoadRuntime("xrCreateInstance");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information");
|
||||||
|
} else {
|
||||||
|
// Load the appropriate layers
|
||||||
|
result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames,
|
||||||
|
api_layer_interfaces);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the loader instance (only send down first runtime interface)
|
||||||
|
LoaderInstance *loader_instance = nullptr;
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
std::unique_ptr<LoaderInstance> owned_loader_instance;
|
||||||
|
result = LoaderInstance::CreateInstance(LoaderXrTermGetInstanceProcAddr, LoaderXrTermCreateInstance,
|
||||||
|
LoaderXrTermCreateApiLayerInstance, std::move(api_layer_interfaces), info,
|
||||||
|
&owned_loader_instance);
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
loader_instance = owned_loader_instance.get();
|
||||||
|
result = ActiveLoaderInstance::Set(std::move(owned_loader_instance), "xrCreateInstance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
// Create a debug utils messenger if the create structure is in the "next" chain
|
||||||
|
const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
|
||||||
|
while (next_header != nullptr) {
|
||||||
|
if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
|
||||||
|
LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain.");
|
||||||
|
dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
|
||||||
|
XrDebugUtilsMessengerEXT messenger;
|
||||||
|
result = LoaderTrampolineCreateDebugUtilsMessengerEXT(loader_instance->GetInstanceHandle(), dbg_utils_create_info,
|
||||||
|
&messenger);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
loader_instance->SetDefaultDebugUtilsMessenger(messenger);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
// Ensure the global loader instance and runtime are destroyed if something went wrong.
|
||||||
|
ActiveLoaderInstance::Remove();
|
||||||
|
RuntimeInterface::UnloadRuntime("xrCreateInstance");
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "xrCreateInstance failed");
|
||||||
|
} else {
|
||||||
|
*instance = loader_instance->GetInstanceHandle();
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline");
|
||||||
|
// Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9
|
||||||
|
if (XR_NULL_HANDLE == instance) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrDestroyInstance", "Instance handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the runtime isn't unloaded while it is being used by xrEnumerateInstanceExtensionProperties.
|
||||||
|
std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyInstance");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
|
||||||
|
// If we allocated a default debug utils messenger, free it
|
||||||
|
XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger();
|
||||||
|
if (messenger != XR_NULL_HANDLE) {
|
||||||
|
LoaderTrampolineDestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now destroy the instance
|
||||||
|
if (XR_FAILED(dispatch_table->DestroyInstance(instance))) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of the loader instance. This will make it possible to create another instance in the future.
|
||||||
|
ActiveLoaderInstance::Remove();
|
||||||
|
|
||||||
|
// Lock the instance create/destroy mutex
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline");
|
||||||
|
|
||||||
|
// Finally, unload the runtime if necessary
|
||||||
|
RuntimeInterface::UnloadRuntime("xrDestroyInstance");
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Core 1.0 manual loader terminator functions
|
||||||
|
|
||||||
|
// Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid.
|
||||||
|
static XrResult ValidateApplicationInfo(const XrApplicationInfo &info) {
|
||||||
|
if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance",
|
||||||
|
"application name missing NULL terminator.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance",
|
||||||
|
"engine name missing NULL terminator.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
if (strlen(info.applicationName) == 0) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance",
|
||||||
|
"VUID-XrApplicationInfo-engineName-parameter: application name can not be empty.");
|
||||||
|
return XR_ERROR_NAME_INVALID;
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that the XrInstanceCreateInfo is valid
|
||||||
|
static XrResult ValidateInstanceCreateInfo(const XrInstanceCreateInfo *info) {
|
||||||
|
// Should have a valid 'type'
|
||||||
|
if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance",
|
||||||
|
"expected XR_TYPE_INSTANCE_CREATE_INFO.");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// Flags must be 0
|
||||||
|
if (0 != info->createFlags) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance",
|
||||||
|
"flags must be 0.");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
// ApplicationInfo struct must be valid
|
||||||
|
XrResult result = ValidateApplicationInfo(info->applicationInfo);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance",
|
||||||
|
"info->applicationInfo is not valid.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers()
|
||||||
|
if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance",
|
||||||
|
"enabledExtensionCount is non-0 but array is NULL");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *createInfo,
|
||||||
|
XrInstance *instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator");
|
||||||
|
XrResult result = ValidateInstanceCreateInfo(createInfo);
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance",
|
||||||
|
"something wrong with XrInstanceCreateInfo contents");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = RuntimeInterface::GetRuntime().CreateInstance(createInfo, instance);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info,
|
||||||
|
const struct XrApiLayerCreateInfo * /*apiLayerInfo*/,
|
||||||
|
XrInstance *instance) {
|
||||||
|
return LoaderXrTermCreateInstance(info, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator");
|
||||||
|
LoaderLogger::GetInstance().RemoveLogRecordersForXrInstance(instance);
|
||||||
|
XrResult result = RuntimeInterface::GetRuntime().DestroyInstance(instance);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance instance, const char *name,
|
||||||
|
PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
|
||||||
|
// A few instance commands need to go through a loader terminator.
|
||||||
|
// Otherwise, go directly to the runtime version of the command if it exists.
|
||||||
|
// But first set the function pointer to NULL so that the fall-through below actually works.
|
||||||
|
*function = nullptr;
|
||||||
|
|
||||||
|
// NOTE: ActiveLoaderInstance cannot be used in this function because it is called before an instance is made active.
|
||||||
|
|
||||||
|
if (0 == strcmp(name, "xrGetInstanceProcAddr")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermGetInstanceProcAddr);
|
||||||
|
} else if (0 == strcmp(name, "xrCreateInstance")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateInstance);
|
||||||
|
} else if (0 == strcmp(name, "xrDestroyInstance")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyInstance);
|
||||||
|
} else if (0 == strcmp(name, "xrSetDebugUtilsObjectNameEXT")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSetDebugUtilsObjectNameEXT);
|
||||||
|
} else if (0 == strcmp(name, "xrCreateDebugUtilsMessengerEXT")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateDebugUtilsMessengerEXT);
|
||||||
|
} else if (0 == strcmp(name, "xrDestroyDebugUtilsMessengerEXT")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyDebugUtilsMessengerEXT);
|
||||||
|
} else if (0 == strcmp(name, "xrSubmitDebugUtilsMessageEXT")) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSubmitDebugUtilsMessageEXT);
|
||||||
|
} else if (0 == strcmp(name, "xrCreateApiLayerInstance")) {
|
||||||
|
// Special layer version of xrCreateInstance terminator. If we get called this by a layer,
|
||||||
|
// we simply re-direct the information back into the standard xrCreateInstance terminator.
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateApiLayerInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != *function) {
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RuntimeInterface::GetInstanceProcAddr(instance, name, function);
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Extension manual loader trampoline functions
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderTrampolineCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline");
|
||||||
|
|
||||||
|
if (instance == XR_NULL_HANDLE) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT", "Instance handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateDebugUtilsMessengerEXT");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = loader_instance->DispatchTable()->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
|
||||||
|
// TODO: get instance from messenger in loader
|
||||||
|
// Also, is the loader really doing all this every call?
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline");
|
||||||
|
|
||||||
|
if (messenger == XR_NULL_HANDLE) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrDestroyDebugUtilsMessengerEXT", "Messenger handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyDebugUtilsMessengerEXT");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = loader_instance->DispatchTable()->DestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
|
||||||
|
if (session == XR_NULL_HANDLE) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrSessionBeginDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == labelInfo) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
|
||||||
|
"xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL",
|
||||||
|
{XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionBeginDebugUtilsLabelRegionEXT");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo);
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
|
||||||
|
return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY {
|
||||||
|
if (session == XR_NULL_HANDLE) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrSessionEndDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionEndDebugUtilsLabelRegionEXT");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::GetInstance().EndLabelRegion(session);
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionEndDebugUtilsLabelRegionEXT) {
|
||||||
|
return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderTrampolineSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
|
||||||
|
if (session == XR_NULL_HANDLE) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrSessionInsertDebugUtilsLabelEXT", "Session handle is XR_NULL_HANDLE.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionInsertDebugUtilsLabelEXT");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == labelInfo) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
|
||||||
|
"xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL",
|
||||||
|
{XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::GetInstance().InsertLabel(session, labelInfo);
|
||||||
|
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
|
||||||
|
if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) {
|
||||||
|
return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderTrampolineSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSetDebugUtilsObjectNameEXT");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->SetDebugUtilsObjectNameEXT(instance, nameInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
|
||||||
|
static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance *loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSubmitDebugUtilsMessageEXT");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result =
|
||||||
|
loader_instance->DispatchTable()->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// ---- Extension manual loader terminator functions
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance,
|
||||||
|
const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
|
||||||
|
XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator");
|
||||||
|
if (nullptr == messenger) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
|
||||||
|
"xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
// This extension is supported entirely by the loader which means the runtime may or may not support it.
|
||||||
|
if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) {
|
||||||
|
result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
|
||||||
|
} else {
|
||||||
|
// Just allocate a character so we have a unique value
|
||||||
|
char *temp_mess_ptr = new char;
|
||||||
|
*messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr);
|
||||||
|
}
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
LoaderLogger::GetInstance().AddLogRecorderForXrInstance(instance, MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger));
|
||||||
|
RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger);
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger));
|
||||||
|
RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger);
|
||||||
|
// This extension is supported entirely by the loader which means the runtime may or may not support it.
|
||||||
|
if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) {
|
||||||
|
result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
|
||||||
|
} else {
|
||||||
|
// Delete the character we would've created
|
||||||
|
delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger)));
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
|
||||||
|
XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) {
|
||||||
|
result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
|
||||||
|
} else {
|
||||||
|
// Only log the message from the loader if the runtime doesn't support this extension. If we did,
|
||||||
|
// then the user would receive multiple instances of the same message.
|
||||||
|
LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData);
|
||||||
|
}
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL
|
||||||
|
LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator");
|
||||||
|
const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) {
|
||||||
|
result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
|
||||||
|
}
|
||||||
|
LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName);
|
||||||
|
LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, const char *name,
|
||||||
|
PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
|
||||||
|
// Initialize the function to nullptr in case it does not get caught in a known case
|
||||||
|
*function = nullptr;
|
||||||
|
|
||||||
|
if (nullptr == function) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
|
||||||
|
"Invalid Function pointer");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr == name) {
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
|
||||||
|
"Invalid Name pointer");
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance *loader_instance = nullptr;
|
||||||
|
if (instance == XR_NULL_HANDLE) {
|
||||||
|
// Null instance is allowed for a few specific API entry points, otherwise return error
|
||||||
|
if (strcmp(name, "xrCreateInstance") != 0 && strcmp(name, "xrEnumerateApiLayerProperties") != 0 &&
|
||||||
|
strcmp(name, "xrEnumerateInstanceExtensionProperties") != 0 && strcmp(name, "xrInitializeLoaderKHR") != 0) {
|
||||||
|
// TODO why is xrGetInstanceProcAddr not listed in here?
|
||||||
|
std::string error_str = "XR_NULL_HANDLE for instance but query for ";
|
||||||
|
error_str += name;
|
||||||
|
error_str += " requires a valid instance";
|
||||||
|
LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-instance-parameter", "xrGetInstanceProcAddr",
|
||||||
|
error_str);
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// non null instance passed in, it should be our current instance
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInstanceProcAddr");
|
||||||
|
if (XR_FAILED(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (loader_instance->GetInstanceHandle() != instance) {
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These functions must always go through the loader's implementation (trampoline).
|
||||||
|
if (strcmp(name, "xrGetInstanceProcAddr") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrGetInstanceProcAddr);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
} else if (strcmp(name, "xrInitializeLoaderKHR") == 0) {
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrInitializeLoaderKHR);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
#else
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
#endif
|
||||||
|
} else if (strcmp(name, "xrEnumerateApiLayerProperties") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateApiLayerProperties);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
} else if (strcmp(name, "xrEnumerateInstanceExtensionProperties") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateInstanceExtensionProperties);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
} else if (strcmp(name, "xrCreateInstance") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrCreateInstance);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
} else if (strcmp(name, "xrDestroyInstance") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrDestroyInstance);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XR_EXT_debug_utils is built into the loader and handled partly through the xrGetInstanceProcAddress terminator,
|
||||||
|
// but the check to see if the extension is enabled must be done here where ActiveLoaderInstance is safe to use.
|
||||||
|
if (*function == nullptr) {
|
||||||
|
if (strcmp(name, "xrCreateDebugUtilsMessengerEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineCreateDebugUtilsMessengerEXT);
|
||||||
|
} else if (strcmp(name, "xrDestroyDebugUtilsMessengerEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineDestroyDebugUtilsMessengerEXT);
|
||||||
|
} else if (strcmp(name, "xrSessionBeginDebugUtilsLabelRegionEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT);
|
||||||
|
} else if (strcmp(name, "xrSessionEndDebugUtilsLabelRegionEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT);
|
||||||
|
} else if (strcmp(name, "xrSessionInsertDebugUtilsLabelEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionInsertDebugUtilsLabelEXT);
|
||||||
|
} else if (strcmp(name, "xrSetDebugUtilsObjectNameEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSetDebugUtilsObjectNameEXT);
|
||||||
|
} else if (strcmp(name, "xrSubmitDebugUtilsMessageEXT") == 0) {
|
||||||
|
*function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSubmitDebugUtilsMessageEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*function != nullptr && !loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
|
||||||
|
// The function matches one of the XR_EXT_debug_utils functions but the extension is not enabled.
|
||||||
|
*function = nullptr;
|
||||||
|
return XR_ERROR_FUNCTION_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*function != nullptr) {
|
||||||
|
// The loader has a trampoline or implementation of this function.
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the function is not supported by the loader, call down to the next layer.
|
||||||
|
return loader_instance->GetInstanceProcAddr(name, function);
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
// Exported loader functions
|
||||||
|
//
|
||||||
|
// The application might override these by exporting the same symbols and so we can't use these
|
||||||
|
// symbols anywhere in the loader code, and instead the internal non exported functions that these
|
||||||
|
// stubs call should be used internally.
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
|
||||||
|
uint32_t *propertyCountOutput,
|
||||||
|
XrApiLayerProperties *properties) {
|
||||||
|
return LoaderXrEnumerateApiLayerProperties(propertyCapacityInput, propertyCountOutput, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(const char *layerName,
|
||||||
|
uint32_t propertyCapacityInput,
|
||||||
|
uint32_t *propertyCountOutput,
|
||||||
|
XrExtensionProperties *properties) {
|
||||||
|
return LoaderXrEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) {
|
||||||
|
return LoaderXrCreateInstance(info, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) { return LoaderXrDestroyInstance(instance); }
|
||||||
|
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char *name,
|
||||||
|
PFN_xrVoidFunction *function) {
|
||||||
|
return LoaderXrGetInstanceProcAddr(instance, name, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) {
|
||||||
|
return LoaderXrInitializeLoaderKHR(loaderInitInfo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
303
thirdparty/openxr/src/loader/loader_instance.cpp
vendored
Normal file
303
thirdparty/openxr/src/loader/loader_instance.cpp
vendored
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "xr_generated_loader.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::unique_ptr<LoaderInstance>& GetSetCurrentLoaderInstance() {
|
||||||
|
static std::unique_ptr<LoaderInstance> current_loader_instance;
|
||||||
|
return current_loader_instance;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace ActiveLoaderInstance {
|
||||||
|
XrResult Set(std::unique_ptr<LoaderInstance> loader_instance, const char* log_function_name) {
|
||||||
|
if (GetSetCurrentLoaderInstance() != nullptr) {
|
||||||
|
LoaderLogger::LogErrorMessage(log_function_name, "Active XrInstance handle already exists");
|
||||||
|
return XR_ERROR_LIMIT_REACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSetCurrentLoaderInstance() = std::move(loader_instance);
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult Get(LoaderInstance** loader_instance, const char* log_function_name) {
|
||||||
|
*loader_instance = GetSetCurrentLoaderInstance().get();
|
||||||
|
if (*loader_instance == nullptr) {
|
||||||
|
LoaderLogger::LogErrorMessage(log_function_name, "No active XrInstance handle.");
|
||||||
|
return XR_ERROR_HANDLE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAvailable() { return GetSetCurrentLoaderInstance() != nullptr; }
|
||||||
|
|
||||||
|
void Remove() { GetSetCurrentLoaderInstance().release(); }
|
||||||
|
} // namespace ActiveLoaderInstance
|
||||||
|
|
||||||
|
// Extensions that are supported by the loader, but may not be supported
|
||||||
|
// the the runtime.
|
||||||
|
const std::array<XrExtensionProperties, 1>& LoaderInstance::LoaderSpecificExtensions() {
|
||||||
|
static const std::array<XrExtensionProperties, 1> extensions = {XrExtensionProperties{
|
||||||
|
XR_TYPE_EXTENSION_PROPERTIES, nullptr, XR_EXT_DEBUG_UTILS_EXTENSION_NAME, XR_EXT_debug_utils_SPEC_VERSION}};
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class InstanceCreateInfoManager {
|
||||||
|
public:
|
||||||
|
explicit InstanceCreateInfoManager(const XrInstanceCreateInfo* info) : original_create_info(info), modified_create_info(*info) {
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the "modified" state to match the original state.
|
||||||
|
void Reset() {
|
||||||
|
enabled_extensions_cstr.clear();
|
||||||
|
enabled_extensions_cstr.reserve(original_create_info->enabledExtensionCount);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < original_create_info->enabledExtensionCount; ++i) {
|
||||||
|
enabled_extensions_cstr.push_back(original_create_info->enabledExtensionNames[i]);
|
||||||
|
}
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove extensions named in the parameter and return a pointer to the current state.
|
||||||
|
const XrInstanceCreateInfo* FilterOutExtensions(const std::vector<const char*>& extensions_to_skip) {
|
||||||
|
if (enabled_extensions_cstr.empty()) {
|
||||||
|
return Get();
|
||||||
|
}
|
||||||
|
if (extensions_to_skip.empty()) {
|
||||||
|
return Get();
|
||||||
|
}
|
||||||
|
for (auto& ext : extensions_to_skip) {
|
||||||
|
FilterOutExtension(ext);
|
||||||
|
}
|
||||||
|
return Update();
|
||||||
|
}
|
||||||
|
// Remove the extension named in the parameter and return a pointer to the current state.
|
||||||
|
const XrInstanceCreateInfo* FilterOutExtension(const char* extension_to_skip) {
|
||||||
|
if (enabled_extensions_cstr.empty()) {
|
||||||
|
return &modified_create_info;
|
||||||
|
}
|
||||||
|
auto b = enabled_extensions_cstr.begin();
|
||||||
|
auto e = enabled_extensions_cstr.end();
|
||||||
|
auto it = std::find_if(b, e, [&](const char* extension) { return strcmp(extension_to_skip, extension) == 0; });
|
||||||
|
if (it != e) {
|
||||||
|
// Just that one element goes away
|
||||||
|
enabled_extensions_cstr.erase(it);
|
||||||
|
}
|
||||||
|
return Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current modified XrInstanceCreateInfo
|
||||||
|
const XrInstanceCreateInfo* Get() const { return &modified_create_info; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const XrInstanceCreateInfo* Update() {
|
||||||
|
modified_create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions_cstr.size());
|
||||||
|
modified_create_info.enabledExtensionNames = enabled_extensions_cstr.empty() ? nullptr : enabled_extensions_cstr.data();
|
||||||
|
return &modified_create_info;
|
||||||
|
}
|
||||||
|
const XrInstanceCreateInfo* original_create_info;
|
||||||
|
|
||||||
|
XrInstanceCreateInfo modified_create_info;
|
||||||
|
std::vector<const char*> enabled_extensions_cstr;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Factory method
|
||||||
|
XrResult LoaderInstance::CreateInstance(PFN_xrGetInstanceProcAddr get_instance_proc_addr_term,
|
||||||
|
PFN_xrCreateInstance create_instance_term,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance_term,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces,
|
||||||
|
const XrInstanceCreateInfo* info, std::unique_ptr<LoaderInstance>* loader_instance) {
|
||||||
|
LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering LoaderInstance::CreateInstance");
|
||||||
|
|
||||||
|
// Check the list of enabled extensions to make sure something supports them, and, if we do,
|
||||||
|
// add it to the list of enabled extensions
|
||||||
|
XrResult last_error = XR_SUCCESS;
|
||||||
|
for (uint32_t ext = 0; ext < info->enabledExtensionCount; ++ext) {
|
||||||
|
bool found = false;
|
||||||
|
// First check the runtime
|
||||||
|
if (RuntimeInterface::GetRuntime().SupportsExtension(info->enabledExtensionNames[ext])) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
// Next check the loader
|
||||||
|
if (!found) {
|
||||||
|
for (auto& loader_extension : LoaderInstance::LoaderSpecificExtensions()) {
|
||||||
|
if (strcmp(loader_extension.extensionName, info->enabledExtensionNames[ext]) == 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, check the enabled layers
|
||||||
|
if (!found) {
|
||||||
|
for (auto& layer_interface : api_layer_interfaces) {
|
||||||
|
if (layer_interface->SupportsExtension(info->enabledExtensionNames[ext])) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
std::string msg = "LoaderInstance::CreateInstance, no support found for requested extension: ";
|
||||||
|
msg += info->enabledExtensionNames[ext];
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", msg);
|
||||||
|
last_error = XR_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Topmost means "closest to the application"
|
||||||
|
PFN_xrGetInstanceProcAddr topmost_gipa = get_instance_proc_addr_term;
|
||||||
|
XrInstance instance{XR_NULL_HANDLE};
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
// Remove the loader-supported-extensions (debug utils), if it's in the list of enabled extensions but not supported by
|
||||||
|
// the runtime.
|
||||||
|
InstanceCreateInfoManager create_info_manager{info};
|
||||||
|
const XrInstanceCreateInfo* modified_create_info = info;
|
||||||
|
if (info->enabledExtensionCount > 0) {
|
||||||
|
std::vector<const char*> extensions_to_skip;
|
||||||
|
for (const auto& ext : LoaderInstance::LoaderSpecificExtensions()) {
|
||||||
|
if (!RuntimeInterface::GetRuntime().SupportsExtension(ext.extensionName)) {
|
||||||
|
extensions_to_skip.emplace_back(ext.extensionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modified_create_info = create_info_manager.FilterOutExtensions(extensions_to_skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only start the xrCreateApiLayerInstance stack if we have layers.
|
||||||
|
if (!api_layer_interfaces.empty()) {
|
||||||
|
// Initialize an array of ApiLayerNextInfo structs
|
||||||
|
std::unique_ptr<XrApiLayerNextInfo[]> next_info_list(new XrApiLayerNextInfo[api_layer_interfaces.size()]);
|
||||||
|
auto ni_index = static_cast<uint32_t>(api_layer_interfaces.size() - 1);
|
||||||
|
for (uint32_t i = 0; i <= ni_index; i++) {
|
||||||
|
next_info_list[i].structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO;
|
||||||
|
next_info_list[i].structVersion = XR_API_LAYER_NEXT_INFO_STRUCT_VERSION;
|
||||||
|
next_info_list[i].structSize = sizeof(XrApiLayerNextInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through all layers, and override the instance pointers with the layer version. However,
|
||||||
|
// go backwards through the layer list so we replace in reverse order so the layers can call their next function
|
||||||
|
// appropriately.
|
||||||
|
PFN_xrCreateApiLayerInstance topmost_cali_fp = create_api_layer_instance_term;
|
||||||
|
XrApiLayerNextInfo* topmost_nextinfo = nullptr;
|
||||||
|
for (auto layer_interface = api_layer_interfaces.rbegin(); layer_interface != api_layer_interfaces.rend();
|
||||||
|
++layer_interface) {
|
||||||
|
// Collect current layer's function pointers
|
||||||
|
PFN_xrGetInstanceProcAddr cur_gipa_fp = (*layer_interface)->GetInstanceProcAddrFuncPointer();
|
||||||
|
PFN_xrCreateApiLayerInstance cur_cali_fp = (*layer_interface)->GetCreateApiLayerInstanceFuncPointer();
|
||||||
|
|
||||||
|
// Fill in layer info and link previous (lower) layer fxn pointers
|
||||||
|
strncpy(next_info_list[ni_index].layerName, (*layer_interface)->LayerName().c_str(),
|
||||||
|
XR_MAX_API_LAYER_NAME_SIZE - 1);
|
||||||
|
next_info_list[ni_index].layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
|
||||||
|
next_info_list[ni_index].next = topmost_nextinfo;
|
||||||
|
next_info_list[ni_index].nextGetInstanceProcAddr = topmost_gipa;
|
||||||
|
next_info_list[ni_index].nextCreateApiLayerInstance = topmost_cali_fp;
|
||||||
|
|
||||||
|
// Update saved pointers for next iteration
|
||||||
|
topmost_nextinfo = &next_info_list[ni_index];
|
||||||
|
topmost_gipa = cur_gipa_fp;
|
||||||
|
topmost_cali_fp = cur_cali_fp;
|
||||||
|
ni_index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the ApiLayerCreateInfo struct and pass to topmost CreateApiLayerInstance()
|
||||||
|
XrApiLayerCreateInfo api_layer_ci = {};
|
||||||
|
api_layer_ci.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO;
|
||||||
|
api_layer_ci.structVersion = XR_API_LAYER_CREATE_INFO_STRUCT_VERSION;
|
||||||
|
api_layer_ci.structSize = sizeof(XrApiLayerCreateInfo);
|
||||||
|
api_layer_ci.loaderInstance = nullptr; // Not used.
|
||||||
|
api_layer_ci.settings_file_location[0] = '\0';
|
||||||
|
api_layer_ci.nextInfo = next_info_list.get();
|
||||||
|
//! @todo do we filter our create info extension list here?
|
||||||
|
//! Think that actually each layer might need to filter...
|
||||||
|
last_error = topmost_cali_fp(modified_create_info, &api_layer_ci, &instance);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The loader's terminator is the topmost CreateInstance if there are no layers.
|
||||||
|
last_error = create_instance_term(modified_create_info, &instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
LoaderLogger::LogErrorMessage("xrCreateInstance", "LoaderInstance::CreateInstance chained CreateInstance call failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
loader_instance->reset(new LoaderInstance(instance, info, topmost_gipa, std::move(api_layer_interfaces)));
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "LoaderInstance::CreateInstance succeeded with ";
|
||||||
|
oss << (*loader_instance)->LayerInterfaces().size();
|
||||||
|
oss << " layers enabled and runtime interface - created instance = ";
|
||||||
|
oss << HandleToHexString((*loader_instance)->GetInstanceHandle());
|
||||||
|
LoaderLogger::LogInfoMessage("xrCreateInstance", oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult LoaderInstance::GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function) {
|
||||||
|
return _topmost_gipa(_runtime_instance, name, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance::LoaderInstance(XrInstance instance, const XrInstanceCreateInfo* create_info, PFN_xrGetInstanceProcAddr topmost_gipa,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces)
|
||||||
|
: _runtime_instance(instance),
|
||||||
|
_topmost_gipa(topmost_gipa),
|
||||||
|
_api_layer_interfaces(std::move(api_layer_interfaces)),
|
||||||
|
_dispatch_table(new XrGeneratedDispatchTable{}) {
|
||||||
|
for (uint32_t ext = 0; ext < create_info->enabledExtensionCount; ++ext) {
|
||||||
|
_enabled_extensions.push_back(create_info->enabledExtensionNames[ext]);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratedXrPopulateDispatchTable(_dispatch_table.get(), instance, topmost_gipa);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderInstance::~LoaderInstance() {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Destroying LoaderInstance = ";
|
||||||
|
oss << PointerToHexString(this);
|
||||||
|
LoaderLogger::LogInfoMessage("xrDestroyInstance", oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoaderInstance::ExtensionIsEnabled(const std::string& extension) {
|
||||||
|
for (std::string& cur_enabled : _enabled_extensions) {
|
||||||
|
if (cur_enabled == extension) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
77
thirdparty/openxr/src/loader/loader_instance.hpp
vendored
Normal file
77
thirdparty/openxr/src/loader/loader_instance.hpp
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ApiLayerInterface;
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
class LoaderInstance;
|
||||||
|
|
||||||
|
// Manage the single loader instance that is available.
|
||||||
|
namespace ActiveLoaderInstance {
|
||||||
|
// Set the active loader instance. This will fail if there is already an active loader instance.
|
||||||
|
XrResult Set(std::unique_ptr<LoaderInstance> loader_instance, const char* log_function_name);
|
||||||
|
|
||||||
|
// Returns true if there is an active loader instance.
|
||||||
|
bool IsAvailable();
|
||||||
|
|
||||||
|
// Get the active LoaderInstance.
|
||||||
|
XrResult Get(LoaderInstance** loader_instance, const char* log_function_name);
|
||||||
|
|
||||||
|
// Destroy the currently active LoaderInstance if there is one. This will make the loader able to create a new XrInstance if needed.
|
||||||
|
void Remove();
|
||||||
|
}; // namespace ActiveLoaderInstance
|
||||||
|
|
||||||
|
// Manages information needed by the loader for an XrInstance, such as what extensions are available and the dispatch table.
|
||||||
|
class LoaderInstance {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult CreateInstance(PFN_xrGetInstanceProcAddr get_instance_proc_addr_term, PFN_xrCreateInstance create_instance_term,
|
||||||
|
PFN_xrCreateApiLayerInstance create_api_layer_instance_term,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> layer_interfaces,
|
||||||
|
const XrInstanceCreateInfo* createInfo, std::unique_ptr<LoaderInstance>* loader_instance);
|
||||||
|
static const std::array<XrExtensionProperties, 1>& LoaderSpecificExtensions();
|
||||||
|
|
||||||
|
virtual ~LoaderInstance();
|
||||||
|
|
||||||
|
XrInstance GetInstanceHandle() { return _runtime_instance; }
|
||||||
|
const std::unique_ptr<XrGeneratedDispatchTable>& DispatchTable() { return _dispatch_table; }
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>>& LayerInterfaces() { return _api_layer_interfaces; }
|
||||||
|
bool ExtensionIsEnabled(const std::string& extension);
|
||||||
|
XrDebugUtilsMessengerEXT DefaultDebugUtilsMessenger() { return _messenger; }
|
||||||
|
void SetDefaultDebugUtilsMessenger(XrDebugUtilsMessengerEXT messenger) { _messenger = messenger; }
|
||||||
|
XrResult GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LoaderInstance(XrInstance instance, const XrInstanceCreateInfo* createInfo, PFN_xrGetInstanceProcAddr topmost_gipa,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces);
|
||||||
|
|
||||||
|
private:
|
||||||
|
XrInstance _runtime_instance{XR_NULL_HANDLE};
|
||||||
|
PFN_xrGetInstanceProcAddr _topmost_gipa{nullptr};
|
||||||
|
std::vector<std::string> _enabled_extensions;
|
||||||
|
std::vector<std::unique_ptr<ApiLayerInterface>> _api_layer_interfaces;
|
||||||
|
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable> _dispatch_table;
|
||||||
|
// Internal debug messenger created during xrCreateInstance
|
||||||
|
XrDebugUtilsMessengerEXT _messenger{XR_NULL_HANDLE};
|
||||||
|
};
|
||||||
239
thirdparty/openxr/src/loader/loader_logger.cpp
vendored
Normal file
239
thirdparty/openxr/src/loader/loader_logger.cpp
vendored
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include "extra_algorithms.h"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
bool LoaderLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT /*message_severity*/,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT /*message_type*/,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* /*callback_data*/) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions for converting to/from XR_EXT_debug_utils values
|
||||||
|
|
||||||
|
XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities) {
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities = 0UL;
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0u) {
|
||||||
|
log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
|
||||||
|
}
|
||||||
|
return log_severities;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities) {
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities = 0UL;
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT) != 0u) {
|
||||||
|
utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
}
|
||||||
|
return utils_severities;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types) {
|
||||||
|
XrLoaderLogMessageTypeFlagBits log_types = 0UL;
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT;
|
||||||
|
}
|
||||||
|
if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0u) {
|
||||||
|
log_types |= XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT;
|
||||||
|
}
|
||||||
|
return log_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types) {
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT utils_types = 0UL;
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
|
||||||
|
}
|
||||||
|
if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT) != 0u) {
|
||||||
|
utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
|
}
|
||||||
|
return utils_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderLogger::LoaderLogger() {
|
||||||
|
std::string debug_string = PlatformUtilsGetEnv("XR_LOADER_DEBUG");
|
||||||
|
|
||||||
|
// Add an error logger by default so that we at least get errors out to std::cerr.
|
||||||
|
// Normally we enable stderr output. But if the XR_LOADER_DEBUG environment variable is
|
||||||
|
// present as "none" then we don't.
|
||||||
|
if (debug_string != "none") {
|
||||||
|
AddLogRecorder(MakeStdErrLoaderLogRecorder(nullptr));
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
// Add a logcat logger by default.
|
||||||
|
AddLogRecorder(MakeLogcatLoaderLogRecorder());
|
||||||
|
#endif // __ANDROID__
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Add an debugger logger by default so that we at least get errors out to the debugger.
|
||||||
|
AddLogRecorder(MakeDebuggerLoaderLogRecorder(nullptr));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If the environment variable to enable loader debugging is set, then enable the
|
||||||
|
// appropriate logging out to std::cout.
|
||||||
|
if (!debug_string.empty()) {
|
||||||
|
XrLoaderLogMessageSeverityFlags debug_flags = {};
|
||||||
|
if (debug_string == "error") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
|
||||||
|
} else if (debug_string == "warn") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
|
||||||
|
} else if (debug_string == "info") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
|
||||||
|
} else if (debug_string == "all" || debug_string == "verbose") {
|
||||||
|
debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
|
||||||
|
}
|
||||||
|
AddLogRecorder(MakeStdOutLoaderLogRecorder(nullptr, debug_flags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) {
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
_recorders.push_back(std::move(recorder));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::AddLogRecorderForXrInstance(XrInstance instance, std::unique_ptr<LoaderLogRecorder>&& recorder) {
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
_recordersByInstance[instance].insert(recorder->UniqueId());
|
||||||
|
_recorders.emplace_back(std::move(recorder));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
vector_remove_if_and_erase(
|
||||||
|
_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) { return recorder->UniqueId() == unique_id; });
|
||||||
|
for (auto& recorders : _recordersByInstance) {
|
||||||
|
auto& messengersForInstance = recorders.second;
|
||||||
|
if (messengersForInstance.count(unique_id) > 0) {
|
||||||
|
messengersForInstance.erase(unique_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::RemoveLogRecordersForXrInstance(XrInstance instance) {
|
||||||
|
std::unique_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
if (_recordersByInstance.find(instance) != _recordersByInstance.end()) {
|
||||||
|
auto recorders = _recordersByInstance[instance];
|
||||||
|
vector_remove_if_and_erase(_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) {
|
||||||
|
return recorders.find(recorder->UniqueId()) != recorders.end();
|
||||||
|
});
|
||||||
|
_recordersByInstance.erase(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoaderLogger::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const std::string& message_id, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects) {
|
||||||
|
XrLoaderLogMessengerCallbackData callback_data = {};
|
||||||
|
callback_data.message_id = message_id.c_str();
|
||||||
|
callback_data.command_name = command_name.c_str();
|
||||||
|
callback_data.message = message.c_str();
|
||||||
|
|
||||||
|
auto names_and_labels = data_.PopulateNamesAndLabels(objects);
|
||||||
|
callback_data.objects = names_and_labels.sdk_objects.empty() ? nullptr : names_and_labels.sdk_objects.data();
|
||||||
|
callback_data.object_count = static_cast<uint8_t>(names_and_labels.objects.size());
|
||||||
|
|
||||||
|
callback_data.session_labels = names_and_labels.labels.empty() ? nullptr : names_and_labels.labels.data();
|
||||||
|
callback_data.session_labels_count = static_cast<uint8_t>(names_and_labels.labels.size());
|
||||||
|
|
||||||
|
std::shared_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
bool exit_app = false;
|
||||||
|
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
|
||||||
|
if ((recorder->MessageSeverities() & message_severity) == message_severity &&
|
||||||
|
(recorder->MessageTypes() & message_type) == message_type) {
|
||||||
|
exit_app |= recorder->LogMessage(message_severity, message_type, &callback_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exit_app;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LoaderLogger::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
|
||||||
|
bool exit_app = false;
|
||||||
|
XrLoaderLogMessageSeverityFlags log_message_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
|
||||||
|
XrLoaderLogMessageTypeFlags log_message_type = DebugUtilsMessageTypesToLoaderLogMessageTypes(message_type);
|
||||||
|
|
||||||
|
AugmentedCallbackData augmented_data;
|
||||||
|
data_.WrapCallbackData(&augmented_data, callback_data);
|
||||||
|
|
||||||
|
// Loop through the recorders
|
||||||
|
std::shared_lock<std::shared_timed_mutex> lock(_mutex);
|
||||||
|
for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
|
||||||
|
// Only send the message if it's a debug utils recorder and of the type the recorder cares about.
|
||||||
|
if (recorder->Type() != XR_LOADER_LOG_DEBUG_UTILS ||
|
||||||
|
(recorder->MessageSeverities() & log_message_severity) != log_message_severity ||
|
||||||
|
(recorder->MessageTypes() & log_message_type) != log_message_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_app |= recorder->LogDebugUtilsMessage(message_severity, message_type, augmented_data.exported_data);
|
||||||
|
}
|
||||||
|
return exit_app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
|
||||||
|
data_.AddObjectName(object_handle, object_type, object_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
|
||||||
|
data_.BeginLabelRegion(session, *label_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::EndLabelRegion(XrSession session) { data_.EndLabelRegion(session); }
|
||||||
|
|
||||||
|
void LoaderLogger::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
|
||||||
|
data_.InsertLabel(session, *label_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoaderLogger::DeleteSessionLabels(XrSession session) { data_.DeleteSessionLabels(session); }
|
||||||
194
thirdparty/openxr/src/loader/loader_logger.hpp
vendored
Normal file
194
thirdparty/openxr/src/loader/loader_logger.hpp
vendored
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "object_info.h"
|
||||||
|
|
||||||
|
// Use internal versions of flags similar to XR_EXT_debug_utils so that
|
||||||
|
// we're not tightly coupled to that extension. This way, if the extension
|
||||||
|
// changes or gets replaced, we can be flexible in the loader.
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT 0x00000001
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT 0x00000010
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT 0x00000100
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT 0x00001000
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_SEVERITY_DEFAULT_BITS 0x00000000
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageSeverityFlagBits;
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageSeverityFlags;
|
||||||
|
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT 0x00000001
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT 0x00000002
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT 0x00000004
|
||||||
|
#define XR_LOADER_LOG_MESSAGE_TYPE_DEFAULT_BITS 0xffffffff
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageTypeFlagBits;
|
||||||
|
typedef XrFlags64 XrLoaderLogMessageTypeFlags;
|
||||||
|
|
||||||
|
struct XrLoaderLogMessengerCallbackData {
|
||||||
|
const char* message_id;
|
||||||
|
const char* command_name;
|
||||||
|
const char* message;
|
||||||
|
uint8_t object_count;
|
||||||
|
XrSdkLogObjectInfo* objects;
|
||||||
|
uint8_t session_labels_count;
|
||||||
|
XrDebugUtilsLabelEXT* session_labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum XrLoaderLogType {
|
||||||
|
XR_LOADER_LOG_UNKNOWN = 0,
|
||||||
|
XR_LOADER_LOG_STDERR,
|
||||||
|
XR_LOADER_LOG_STDOUT,
|
||||||
|
XR_LOADER_LOG_DEBUG_UTILS,
|
||||||
|
XR_LOADER_LOG_DEBUGGER,
|
||||||
|
XR_LOADER_LOG_LOGCAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
LoaderLogRecorder(XrLoaderLogType type, void* user_data, XrLoaderLogMessageSeverityFlags message_severities,
|
||||||
|
XrLoaderLogMessageTypeFlags message_types) {
|
||||||
|
_active = false;
|
||||||
|
_user_data = user_data;
|
||||||
|
_type = type;
|
||||||
|
_unique_id = 0;
|
||||||
|
_message_severities = message_severities;
|
||||||
|
_message_types = message_types;
|
||||||
|
}
|
||||||
|
virtual ~LoaderLogRecorder() = default;
|
||||||
|
|
||||||
|
XrLoaderLogType Type() { return _type; }
|
||||||
|
|
||||||
|
uint64_t UniqueId() { return _unique_id; }
|
||||||
|
|
||||||
|
XrLoaderLogMessageSeverityFlags MessageSeverities() { return _message_severities; }
|
||||||
|
|
||||||
|
XrLoaderLogMessageTypeFlags MessageTypes() { return _message_types; }
|
||||||
|
|
||||||
|
virtual void Start() { _active = true; }
|
||||||
|
|
||||||
|
bool IsPaused() { return _active; }
|
||||||
|
|
||||||
|
virtual void Pause() { _active = false; }
|
||||||
|
|
||||||
|
virtual void Resume() { _active = true; }
|
||||||
|
|
||||||
|
virtual void Stop() { _active = false; }
|
||||||
|
|
||||||
|
virtual bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) = 0;
|
||||||
|
|
||||||
|
// Extension-specific logging functions - defaults to do nothing.
|
||||||
|
virtual bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _active;
|
||||||
|
XrLoaderLogType _type;
|
||||||
|
uint64_t _unique_id;
|
||||||
|
void* _user_data;
|
||||||
|
XrLoaderLogMessageSeverityFlags _message_severities;
|
||||||
|
XrLoaderLogMessageTypeFlags _message_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoaderLogger {
|
||||||
|
public:
|
||||||
|
static LoaderLogger& GetInstance() {
|
||||||
|
static LoaderLogger instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder);
|
||||||
|
void RemoveLogRecorder(uint64_t unique_id);
|
||||||
|
|
||||||
|
void AddLogRecorderForXrInstance(XrInstance instance, std::unique_ptr<LoaderLogRecorder>&& recorder);
|
||||||
|
void RemoveLogRecordersForXrInstance(XrInstance instance);
|
||||||
|
|
||||||
|
//! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
|
||||||
|
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
|
||||||
|
void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info);
|
||||||
|
void EndLabelRegion(XrSession session);
|
||||||
|
void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info);
|
||||||
|
void DeleteSessionLabels(XrSession session);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const std::string& message_id, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {});
|
||||||
|
static bool LogErrorMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogWarningMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogInfoMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogVerboseMessage(const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
|
||||||
|
"OpenXR-Loader", command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogValidationErrorMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
|
||||||
|
vuid, command_name, message, objects);
|
||||||
|
}
|
||||||
|
static bool LogValidationWarningMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
|
||||||
|
const std::vector<XrSdkLogObjectInfo>& objects = {}) {
|
||||||
|
return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
|
||||||
|
vuid, command_name, message, objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
|
||||||
|
|
||||||
|
// Non-copyable
|
||||||
|
LoaderLogger(const LoaderLogger&) = delete;
|
||||||
|
LoaderLogger& operator=(const LoaderLogger&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LoaderLogger();
|
||||||
|
|
||||||
|
std::shared_timed_mutex _mutex;
|
||||||
|
|
||||||
|
// List of *all* available recorder objects (including created specifically for an Instance)
|
||||||
|
std::vector<std::unique_ptr<LoaderLogRecorder>> _recorders;
|
||||||
|
|
||||||
|
// List of recorder objects only created specifically for an XrInstance
|
||||||
|
std::unordered_map<XrInstance, std::unordered_set<uint64_t>> _recordersByInstance;
|
||||||
|
|
||||||
|
DebugUtilsData data_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utility functions for converting to/from XR_EXT_debug_utils values
|
||||||
|
XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severities);
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
|
||||||
|
XrLoaderLogMessageSeverityFlags log_severities);
|
||||||
|
XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types);
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types);
|
||||||
291
thirdparty/openxr/src/loader/loader_logger_recorders.cpp
vendored
Normal file
291
thirdparty/openxr/src/loader/loader_logger_recorders.cpp
vendored
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "loader_logger_recorders.hpp"
|
||||||
|
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include "android/log.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Anonymous namespace to keep these types private
|
||||||
|
namespace {
|
||||||
|
void OutputMessageToStream(std::ostream& os, XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type, const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
if (XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT > message_severity) {
|
||||||
|
os << "Verbose [";
|
||||||
|
} else if (XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT > message_severity) {
|
||||||
|
os << "Info [";
|
||||||
|
} else if (XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT > message_severity) {
|
||||||
|
os << "Warning [";
|
||||||
|
} else {
|
||||||
|
os << "Error [";
|
||||||
|
}
|
||||||
|
switch (message_type) {
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT:
|
||||||
|
os << "GENERAL";
|
||||||
|
break;
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT:
|
||||||
|
os << "SPEC";
|
||||||
|
break;
|
||||||
|
case XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT:
|
||||||
|
os << "PERF";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
os << "UNKNOWN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os << " | " << callback_data->command_name << " | " << callback_data->message_id << "] : " << callback_data->message
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
for (uint32_t obj = 0; obj < callback_data->object_count; ++obj) {
|
||||||
|
os << " Object[" << obj << "] = " << callback_data->objects[obj].ToString();
|
||||||
|
os << std::endl;
|
||||||
|
}
|
||||||
|
for (uint32_t label = 0; label < callback_data->session_labels_count; ++label) {
|
||||||
|
os << " SessionLabel[" << std::to_string(label) << "] = " << callback_data->session_labels[label].labelName;
|
||||||
|
os << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// With std::cerr: Standard Error logger, always on for now
|
||||||
|
// With std::cout: Standard Output logger used with XR_LOADER_DEBUG
|
||||||
|
class OstreamLoaderLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream& os_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Debug Utils logger used with XR_EXT_debug_utils
|
||||||
|
class DebugUtilsLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info, XrDebugUtilsMessengerEXT debug_messenger);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PFN_xrDebugUtilsMessengerCallbackEXT _user_callback;
|
||||||
|
};
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
|
class LogcatLoaderLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
LogcatLoaderLogRecorder();
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Output to debugger
|
||||||
|
class DebuggerLoaderLogRecorder : public LoaderLogRecorder {
|
||||||
|
public:
|
||||||
|
DebuggerLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
|
||||||
|
|
||||||
|
bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Unified stdout/stderr logger
|
||||||
|
OstreamLoaderLogRecorder::OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags)
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_STDOUT, user_data, flags, 0xFFFFFFFFUL), os_(os) {
|
||||||
|
// Automatically start
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OstreamLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
OutputMessageToStream(os_, message_severity, message_type, callback_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return of "true" means that we should exit the application after the logged message. We
|
||||||
|
// don't want to do that for our internal logging. Only let a user return true.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A logger associated with the XR_EXT_debug_utils extension
|
||||||
|
|
||||||
|
DebugUtilsLogRecorder::DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger)
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_DEBUG_UTILS, static_cast<void*>(create_info->userData),
|
||||||
|
DebugUtilsSeveritiesToLoaderLogMessageSeverities(create_info->messageSeverities),
|
||||||
|
DebugUtilsMessageTypesToLoaderLogMessageTypes(create_info->messageTypes)),
|
||||||
|
_user_callback(create_info->userCallback) {
|
||||||
|
// Use the debug messenger value to uniquely identify this logger with that messenger
|
||||||
|
_unique_id = MakeHandleGeneric(debug_messenger);
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension-specific logging functions
|
||||||
|
bool DebugUtilsLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
bool should_exit = false;
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
XrDebugUtilsMessageSeverityFlagsEXT utils_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT utils_type = LoaderLogMessageTypesToDebugUtilsMessageTypes(message_type);
|
||||||
|
|
||||||
|
// Convert the loader log message into the debug utils log message information
|
||||||
|
XrDebugUtilsMessengerCallbackDataEXT utils_callback_data = {};
|
||||||
|
utils_callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
|
||||||
|
utils_callback_data.messageId = callback_data->message_id;
|
||||||
|
utils_callback_data.functionName = callback_data->command_name;
|
||||||
|
utils_callback_data.message = callback_data->message;
|
||||||
|
std::vector<XrDebugUtilsObjectNameInfoEXT> utils_objects;
|
||||||
|
utils_objects.resize(callback_data->object_count);
|
||||||
|
for (uint8_t object = 0; object < callback_data->object_count; ++object) {
|
||||||
|
utils_objects[object].type = XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
utils_objects[object].next = nullptr;
|
||||||
|
utils_objects[object].objectHandle = callback_data->objects[object].handle;
|
||||||
|
utils_objects[object].objectType = callback_data->objects[object].type;
|
||||||
|
utils_objects[object].objectName = callback_data->objects[object].name.c_str();
|
||||||
|
}
|
||||||
|
utils_callback_data.objectCount = callback_data->object_count;
|
||||||
|
utils_callback_data.objects = utils_objects.data();
|
||||||
|
utils_callback_data.sessionLabelCount = callback_data->session_labels_count;
|
||||||
|
utils_callback_data.sessionLabels = callback_data->session_labels;
|
||||||
|
|
||||||
|
// Call the user callback with the appropriate info
|
||||||
|
// Return of "true" means that we should exit the application after the logged message.
|
||||||
|
should_exit = (_user_callback(utils_severity, utils_type, &utils_callback_data, _user_data) == XR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return should_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugUtilsLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
|
||||||
|
XrDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
|
const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
|
||||||
|
// Call the user callback with the appropriate info
|
||||||
|
// Return of "true" means that we should exit the application after the logged message.
|
||||||
|
return (_user_callback(message_severity, message_type, callback_data, _user_data) == XR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
|
static inline android_LogPriority LoaderToAndroidLogPriority(XrLoaderLogMessageSeverityFlags message_severity) {
|
||||||
|
if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT)) {
|
||||||
|
return ANDROID_LOG_ERROR;
|
||||||
|
}
|
||||||
|
if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT)) {
|
||||||
|
return ANDROID_LOG_WARN;
|
||||||
|
}
|
||||||
|
if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT)) {
|
||||||
|
return ANDROID_LOG_INFO;
|
||||||
|
}
|
||||||
|
return ANDROID_LOG_VERBOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogcatLoaderLogRecorder::LogcatLoaderLogRecorder()
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_LOGCAT, nullptr,
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT |
|
||||||
|
XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT,
|
||||||
|
0xFFFFFFFFUL) {
|
||||||
|
// Automatically start
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogcatLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
std::stringstream ss;
|
||||||
|
OutputMessageToStream(ss, message_severity, message_type, callback_data);
|
||||||
|
__android_log_write(LoaderToAndroidLogPriority(message_severity), "OpenXR-Loader", ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return of "true" means that we should exit the application after the logged message. We
|
||||||
|
// don't want to do that for our internal logging. Only let a user return true.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // __ANDROID__
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Unified stdout/stderr logger
|
||||||
|
DebuggerLoaderLogRecorder::DebuggerLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags)
|
||||||
|
: LoaderLogRecorder(XR_LOADER_LOG_DEBUGGER, user_data, flags, 0xFFFFFFFFUL) {
|
||||||
|
// Automatically start
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebuggerLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
|
||||||
|
XrLoaderLogMessageTypeFlags message_type,
|
||||||
|
const XrLoaderLogMessengerCallbackData* callback_data) {
|
||||||
|
if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
|
||||||
|
std::stringstream ss;
|
||||||
|
OutputMessageToStream(ss, message_severity, message_type, callback_data);
|
||||||
|
|
||||||
|
OutputDebugStringA(ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return of "true" means that we should exit the application after the logged message. We
|
||||||
|
// don't want to do that for our internal logging. Only let a user return true.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new OstreamLoaderLogRecorder(std::cout, user_data, flags));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(
|
||||||
|
new OstreamLoaderLogRecorder(std::cerr, user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new DebugUtilsLogRecorder(create_info, debug_messenger));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeLogcatLoaderLogRecorder() {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new LogcatLoaderLogRecorder());
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebuggerLoaderLogRecorder(void* user_data) {
|
||||||
|
std::unique_ptr<LoaderLogRecorder> recorder(new DebuggerLoaderLogRecorder(user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
|
||||||
|
return recorder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
40
thirdparty/openxr/src/loader/loader_logger_recorders.hpp
vendored
Normal file
40
thirdparty/openxr/src/loader/loader_logger_recorders.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
//! Standard Error logger, on by default. Disabled with environment variable XR_LOADER_DEBUG = "none".
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data);
|
||||||
|
|
||||||
|
//! Standard Output logger used with XR_LOADER_DEBUG environment variable.
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
//! Android liblog ("logcat") logger
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeLogcatLoaderLogRecorder();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Debug Utils logger used with XR_EXT_debug_utils
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
|
XrDebugUtilsMessengerEXT debug_messenger);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
//! Win32 debugger output
|
||||||
|
std::unique_ptr<LoaderLogRecorder> MakeDebuggerLoaderLogRecorder(void* user_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: Add other Derived classes:
|
||||||
|
// - FileLoaderLogRecorder - During/after xrCreateInstance
|
||||||
|
// - PipeLoaderLogRecorder? - During/after xrCreateInstance
|
||||||
204
thirdparty/openxr/src/loader/loader_platform.hpp
vendored
Normal file
204
thirdparty/openxr/src/loader/loader_platform.hpp
vendored
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
#define LOADER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
||||||
|
#define LOADER_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define LOADER_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Environment variables
|
||||||
|
#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE) || defined(XR_OS_ANDROID)
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
|
||||||
|
// Dynamic Loading of libraries:
|
||||||
|
typedef void *LoaderPlatformLibraryHandle;
|
||||||
|
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
|
||||||
|
// resolved at this time (which improves performance). Note that if not all symbols
|
||||||
|
// can be resolved, this could cause crashes later.
|
||||||
|
// For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all
|
||||||
|
// symbols to be resolved here.
|
||||||
|
return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
(void)path;
|
||||||
|
return dlerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }
|
||||||
|
|
||||||
|
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
assert(library);
|
||||||
|
assert(!name.empty());
|
||||||
|
return dlsym(library, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
|
||||||
|
(void)name;
|
||||||
|
return dlerror();
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(XR_OS_WINDOWS)
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ';'
|
||||||
|
#define DIRECTORY_SYMBOL '\\'
|
||||||
|
|
||||||
|
// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {
|
||||||
|
int32_t copy_count = -1;
|
||||||
|
if (buffer_size != 0) {
|
||||||
|
copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);
|
||||||
|
}
|
||||||
|
if (copy_count == -1) {
|
||||||
|
copy_count = _vscprintf(print_format, varying_list);
|
||||||
|
}
|
||||||
|
return copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {
|
||||||
|
va_list varying_list;
|
||||||
|
va_start(varying_list, print_format);
|
||||||
|
int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);
|
||||||
|
va_end(varying_list);
|
||||||
|
return copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define snprintf xr_snprintf
|
||||||
|
#define vsnprintf xr_vsnprintf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
if (prefixErrorCode) {
|
||||||
|
char prefixBuffer[64];
|
||||||
|
snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);
|
||||||
|
str = prefixBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.
|
||||||
|
WCHAR errorBufferW[1024]{};
|
||||||
|
const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);
|
||||||
|
const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);
|
||||||
|
|
||||||
|
if (length) { // If errorBufferW contains what we are looking for...
|
||||||
|
str += wide_to_utf8(errorBufferW);
|
||||||
|
} else {
|
||||||
|
str = "(unknown)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic Loading:
|
||||||
|
typedef HMODULE LoaderPlatformLibraryHandle;
|
||||||
|
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
const std::wstring pathW = utf8_to_wide(path);
|
||||||
|
|
||||||
|
// Try loading the library the original way first.
|
||||||
|
LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());
|
||||||
|
|
||||||
|
if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
|
||||||
|
const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());
|
||||||
|
const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||||
|
if (fileExists) {
|
||||||
|
// If that failed, then try loading it with broader search folders.
|
||||||
|
handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
std::stringstream ss;
|
||||||
|
const DWORD dwLastError = GetLastError();
|
||||||
|
const std::string strError = DescribeError(dwLastError);
|
||||||
|
ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }
|
||||||
|
|
||||||
|
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
assert(library);
|
||||||
|
assert(name.size() > 0);
|
||||||
|
return reinterpret_cast<void *>(GetProcAddress(library, name.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Failed to find function " << name << " in dynamic library";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // Not Linux or Windows
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ':'
|
||||||
|
#define DIRECTORY_SYMBOL '/'
|
||||||
|
|
||||||
|
static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
|
||||||
|
// Stub func
|
||||||
|
#error("Unknown platform, undefined dynamic library routines resulting");
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
|
||||||
|
// Stub func
|
||||||
|
(void)path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {
|
||||||
|
// Stub func
|
||||||
|
(void)library;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
|
||||||
|
// Stub func
|
||||||
|
void(library);
|
||||||
|
void(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
|
||||||
|
// Stub func
|
||||||
|
(void)name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
845
thirdparty/openxr/src/loader/manifest_file.cpp
vendored
Normal file
845
thirdparty/openxr/src/loader/manifest_file.cpp
vendored
Normal file
@@ -0,0 +1,845 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
|
||||||
|
#ifdef OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
#include "common_config.h"
|
||||||
|
#endif // OPENXR_HAVE_COMMON_CONFIG
|
||||||
|
|
||||||
|
#include "filesystem_utils.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "platform_utils.hpp"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef FALLBACK_CONFIG_DIRS
|
||||||
|
#define FALLBACK_CONFIG_DIRS "/etc/xdg"
|
||||||
|
#endif // !FALLBACK_CONFIG_DIRS
|
||||||
|
|
||||||
|
#ifndef FALLBACK_DATA_DIRS
|
||||||
|
#define FALLBACK_DATA_DIRS "/usr/local/share:/usr/share"
|
||||||
|
#endif // !FALLBACK_DATA_DIRS
|
||||||
|
|
||||||
|
#ifndef SYSCONFDIR
|
||||||
|
#define SYSCONFDIR "/etc"
|
||||||
|
#endif // !SYSCONFDIR
|
||||||
|
|
||||||
|
#ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING
|
||||||
|
#if JSON_USE_EXCEPTIONS
|
||||||
|
#error \
|
||||||
|
"Loader is configured to not catch exceptions, but jsoncpp was built with exception-throwing enabled, which could violate the C ABI. One of those two things needs to change."
|
||||||
|
#endif // JSON_USE_EXCEPTIONS
|
||||||
|
#endif // !XRLOADER_DISABLE_EXCEPTION_HANDLING
|
||||||
|
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
|
||||||
|
// Utility functions for finding files in the appropriate paths
|
||||||
|
|
||||||
|
static inline bool StringEndsWith(const std::string &value, const std::string &ending) {
|
||||||
|
if (ending.size() > value.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file found is a manifest file name, add it to the out_files manifest list.
|
||||||
|
static void AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) {
|
||||||
|
if (full_file.empty() || !StringEndsWith(full_file, ".json")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manifest_files.push_back(full_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the current path for any manifest files. If the provided search_path is a directory, look for
|
||||||
|
// all included JSON files in that directory. Otherwise, just check the provided search_path which should
|
||||||
|
// be a single filename.
|
||||||
|
static void CheckAllFilesInThePath(const std::string &search_path, bool is_directory_list,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
if (FileSysUtilsPathExists(search_path)) {
|
||||||
|
std::string absolute_path;
|
||||||
|
if (!is_directory_list) {
|
||||||
|
// If the file exists, try to add it
|
||||||
|
if (FileSysUtilsIsRegularFile(search_path)) {
|
||||||
|
FileSysUtilsGetAbsolutePath(search_path, absolute_path);
|
||||||
|
AddIfJson(absolute_path, manifest_files);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::vector<std::string> files;
|
||||||
|
if (FileSysUtilsFindFilesInPath(search_path, files)) {
|
||||||
|
for (std::string &cur_file : files) {
|
||||||
|
std::string relative_path;
|
||||||
|
FileSysUtilsCombinePaths(search_path, cur_file, relative_path);
|
||||||
|
if (!FileSysUtilsGetAbsolutePath(relative_path, absolute_path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AddIfJson(absolute_path, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all manifest files in the provided paths to the manifest_files list. If search_path
|
||||||
|
// is made up of directory listings (versus direct manifest file names) search each path for
|
||||||
|
// any manifest files.
|
||||||
|
static void AddFilesInPath(const std::string &search_path, bool is_directory_list, std::vector<std::string> &manifest_files) {
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = search_path.find_first_of(PATH_SEPARATOR);
|
||||||
|
std::string cur_search;
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
// substr takes a start index and length.
|
||||||
|
std::size_t length = found - last_found;
|
||||||
|
cur_search = search_path.substr(last_found, length);
|
||||||
|
|
||||||
|
CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
|
||||||
|
|
||||||
|
// This works around issue if multiple path separator follow each other directly.
|
||||||
|
last_found = found;
|
||||||
|
while (found == last_found) {
|
||||||
|
last_found = found + 1;
|
||||||
|
found = search_path.find_first_of(PATH_SEPARATOR, last_found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
if (last_found < search_path.size()) {
|
||||||
|
cur_search = search_path.substr(last_found);
|
||||||
|
CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all paths listed in the cur_path string into output_path and append the appropriate relative_path onto the end of each.
|
||||||
|
static void CopyIncludedPaths(bool is_directory_list, const std::string &cur_path, const std::string &relative_path,
|
||||||
|
std::string &output_path) {
|
||||||
|
if (!cur_path.empty()) {
|
||||||
|
std::size_t last_found = 0;
|
||||||
|
std::size_t found = cur_path.find_first_of(PATH_SEPARATOR);
|
||||||
|
|
||||||
|
// Handle any path listings in the string (separated by the appropriate path separator)
|
||||||
|
while (found != std::string::npos) {
|
||||||
|
std::size_t length = found - last_found;
|
||||||
|
output_path += cur_path.substr(last_found, length);
|
||||||
|
if (is_directory_list && (cur_path[found - 1] != '\\' && cur_path[found - 1] != '/')) {
|
||||||
|
output_path += DIRECTORY_SYMBOL;
|
||||||
|
}
|
||||||
|
output_path += relative_path;
|
||||||
|
output_path += PATH_SEPARATOR;
|
||||||
|
|
||||||
|
last_found = found;
|
||||||
|
found = cur_path.find_first_of(PATH_SEPARATOR, found + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's something remaining in the string, copy it over
|
||||||
|
size_t last_char = cur_path.size() - 1;
|
||||||
|
if (last_found != last_char) {
|
||||||
|
output_path += cur_path.substr(last_found);
|
||||||
|
if (is_directory_list && (cur_path[last_char] != '\\' && cur_path[last_char] != '/')) {
|
||||||
|
output_path += DIRECTORY_SYMBOL;
|
||||||
|
}
|
||||||
|
output_path += relative_path;
|
||||||
|
output_path += PATH_SEPARATOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for data files in the provided paths, but first check the environment override to determine if we should use that instead.
|
||||||
|
static void ReadDataFilesInSearchPaths(const std::string &override_env_var, const std::string &relative_path, bool &override_active,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
std::string override_path;
|
||||||
|
std::string search_path;
|
||||||
|
|
||||||
|
if (!override_env_var.empty()) {
|
||||||
|
bool permit_override = true;
|
||||||
|
#ifndef XR_OS_WINDOWS
|
||||||
|
if (geteuid() != getuid() || getegid() != getgid()) {
|
||||||
|
// Don't allow setuid apps to use the env var
|
||||||
|
permit_override = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (permit_override) {
|
||||||
|
override_path = PlatformUtilsGetSecureEnv(override_env_var.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!override_path.empty()) {
|
||||||
|
CopyIncludedPaths(true, override_path, "", search_path);
|
||||||
|
override_active = true;
|
||||||
|
} else {
|
||||||
|
override_active = false;
|
||||||
|
#if !defined(XR_OS_WINDOWS) && !defined(XR_OS_ANDROID)
|
||||||
|
const char home_additional[] = ".local/share/";
|
||||||
|
|
||||||
|
// Determine how much space is needed to generate the full search path
|
||||||
|
// for the current manifest files.
|
||||||
|
std::string xdg_conf_dirs = PlatformUtilsGetSecureEnv("XDG_CONFIG_DIRS");
|
||||||
|
std::string xdg_data_dirs = PlatformUtilsGetSecureEnv("XDG_DATA_DIRS");
|
||||||
|
std::string xdg_data_home = PlatformUtilsGetSecureEnv("XDG_DATA_HOME");
|
||||||
|
std::string home = PlatformUtilsGetSecureEnv("HOME");
|
||||||
|
|
||||||
|
if (xdg_conf_dirs.empty()) {
|
||||||
|
CopyIncludedPaths(true, FALLBACK_CONFIG_DIRS, relative_path, search_path);
|
||||||
|
} else {
|
||||||
|
CopyIncludedPaths(true, xdg_conf_dirs, relative_path, search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyIncludedPaths(true, SYSCONFDIR, relative_path, search_path);
|
||||||
|
#if defined(EXTRASYSCONFDIR)
|
||||||
|
CopyIncludedPaths(true, EXTRASYSCONFDIR, relative_path, search_path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (xdg_data_dirs.empty()) {
|
||||||
|
CopyIncludedPaths(true, FALLBACK_DATA_DIRS, relative_path, search_path);
|
||||||
|
} else {
|
||||||
|
CopyIncludedPaths(true, xdg_data_dirs, relative_path, search_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xdg_data_home.empty()) {
|
||||||
|
CopyIncludedPaths(true, xdg_data_home, relative_path, search_path);
|
||||||
|
} else if (!home.empty()) {
|
||||||
|
std::string relative_home_path = home_additional;
|
||||||
|
relative_home_path += relative_path;
|
||||||
|
CopyIncludedPaths(true, home, relative_home_path, search_path);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)relative_path;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, parse the paths and add any manifest files found in them.
|
||||||
|
AddFilesInPath(search_path, true, manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XR_OS_LINUX
|
||||||
|
|
||||||
|
// Get an XDG environment variable with a $HOME-relative default
|
||||||
|
static std::string GetXDGEnvHome(const char *name, const char *fallback_path) {
|
||||||
|
std::string result = PlatformUtilsGetSecureEnv(name);
|
||||||
|
if (!result.empty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = PlatformUtilsGetSecureEnv("HOME");
|
||||||
|
if (result.empty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result += "/";
|
||||||
|
result += fallback_path;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get an XDG environment variable with absolute defaults
|
||||||
|
static std::string GetXDGEnvAbsolute(const char *name, const char *fallback_paths) {
|
||||||
|
std::string result = PlatformUtilsGetSecureEnv(name);
|
||||||
|
if (!result.empty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return fallback_paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the first instance of relative_path occurring in an XDG config dir according to standard
|
||||||
|
// precedence order.
|
||||||
|
static bool FindXDGConfigFile(const std::string &relative_path, std::string &out) {
|
||||||
|
out = GetXDGEnvHome("XDG_CONFIG_HOME", ".config");
|
||||||
|
if (!out.empty()) {
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
|
||||||
|
LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in XDG_CONFIG_HOME: " + out);
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istringstream iss(GetXDGEnvAbsolute("XDG_CONFIG_DIRS", FALLBACK_CONFIG_DIRS));
|
||||||
|
std::string path;
|
||||||
|
while (std::getline(iss, path, PATH_SEPARATOR)) {
|
||||||
|
if (path.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out = path;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in an entry of XDG_CONFIG_DIRS: " + out);
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out = SYSCONFDIR;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in compiled-in SYSCONFDIR: " + out);
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(EXTRASYSCONFDIR)
|
||||||
|
out = EXTRASYSCONFDIR;
|
||||||
|
out += "/";
|
||||||
|
out += relative_path;
|
||||||
|
LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in compiled-in EXTRASYSCONFDIR: " + out);
|
||||||
|
if (FileSysUtilsPathExists(out)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
|
||||||
|
// Look for runtime data files in the provided paths, but first check the environment override to determine
|
||||||
|
// if we should use that instead.
|
||||||
|
static void ReadRuntimeDataFilesInRegistry(const std::string &runtime_registry_location,
|
||||||
|
const std::string &default_runtime_value_name,
|
||||||
|
std::vector<std::string> &manifest_files) {
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD access_flags;
|
||||||
|
wchar_t value_w[1024];
|
||||||
|
DWORD value_size_w = sizeof(value_w); // byte size of the buffer.
|
||||||
|
|
||||||
|
// Generate the full registry location for the registry information
|
||||||
|
std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
|
||||||
|
full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
|
||||||
|
full_registry_location += runtime_registry_location;
|
||||||
|
|
||||||
|
const std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
|
||||||
|
const std::wstring default_runtime_value_name_w = utf8_to_wide(default_runtime_value_name);
|
||||||
|
|
||||||
|
// Use 64 bit regkey for 64bit application, and use 32 bit regkey in WOW for 32bit application.
|
||||||
|
access_flags = KEY_QUERY_VALUE;
|
||||||
|
LONG open_value = RegOpenKeyExW(HKEY_LOCAL_MACHINE, full_registry_location_w.c_str(), 0, access_flags, &hkey);
|
||||||
|
|
||||||
|
if (ERROR_SUCCESS != open_value) {
|
||||||
|
LoaderLogger::LogWarningMessage("",
|
||||||
|
"ReadRuntimeDataFilesInRegistry - failed to open registry key " + full_registry_location);
|
||||||
|
} else if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
|
||||||
|
RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL,
|
||||||
|
reinterpret_cast<LPBYTE>(&value_w), &value_size_w)) {
|
||||||
|
LoaderLogger::LogWarningMessage(
|
||||||
|
"", "ReadRuntimeDataFilesInRegistry - failed to read registry value " + default_runtime_value_name);
|
||||||
|
} else {
|
||||||
|
AddFilesInPath(wide_to_utf8(value_w), false, manifest_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for layer data files in the provided paths, but first check the environment override to determine
|
||||||
|
// if we should use that instead.
|
||||||
|
static void ReadLayerDataFilesInRegistry(const std::string ®istry_location, std::vector<std::string> &manifest_files) {
|
||||||
|
const std::wstring full_registry_location_w =
|
||||||
|
utf8_to_wide(OPENXR_REGISTRY_LOCATION + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + registry_location);
|
||||||
|
|
||||||
|
auto ReadLayerDataFilesInHive = [&](HKEY hive) {
|
||||||
|
HKEY hkey;
|
||||||
|
LONG open_value = RegOpenKeyExW(hive, full_registry_location_w.c_str(), 0, KEY_QUERY_VALUE, &hkey);
|
||||||
|
if (ERROR_SUCCESS != open_value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t name_w[1024]{};
|
||||||
|
LONG rtn_value;
|
||||||
|
DWORD name_size = 1023;
|
||||||
|
DWORD value;
|
||||||
|
DWORD value_size = sizeof(value);
|
||||||
|
DWORD key_index = 0;
|
||||||
|
while (ERROR_SUCCESS ==
|
||||||
|
(rtn_value = RegEnumValueW(hkey, key_index++, name_w, &name_size, NULL, NULL, (LPBYTE)&value, &value_size))) {
|
||||||
|
if (value_size == sizeof(value) && value == 0) {
|
||||||
|
const std::string filename = wide_to_utf8(name_w);
|
||||||
|
AddFilesInPath(filename, false, manifest_files);
|
||||||
|
}
|
||||||
|
// Reset some items for the next loop
|
||||||
|
name_size = 1023;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Do not allow high integrity processes to act on data that can be controlled by medium integrity processes.
|
||||||
|
const bool readFromCurrentUser = !IsHighIntegrityLevel();
|
||||||
|
|
||||||
|
bool found = ReadLayerDataFilesInHive(HKEY_LOCAL_MACHINE);
|
||||||
|
if (readFromCurrentUser) {
|
||||||
|
found |= ReadLayerDataFilesInHive(HKEY_CURRENT_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry location ";
|
||||||
|
warning_message += registry_location;
|
||||||
|
warning_message += (readFromCurrentUser ? " in either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER" : " in HKEY_LOCAL_MACHINE");
|
||||||
|
LoaderLogger::LogWarningMessage("", warning_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XR_OS_WINDOWS
|
||||||
|
|
||||||
|
ManifestFile::ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path)
|
||||||
|
: _filename(filename), _type(type), _library_path(library_path) {}
|
||||||
|
|
||||||
|
bool ManifestFile::IsValidJson(const Json::Value &root_node, JsonVersion &version) {
|
||||||
|
if (root_node["file_format_version"].isNull() || !root_node["file_format_version"].isString()) {
|
||||||
|
LoaderLogger::LogErrorMessage("", "ManifestFile::IsValidJson - JSON file missing \"file_format_version\"");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string file_format = root_node["file_format_version"].asString();
|
||||||
|
const int num_fields = sscanf(file_format.c_str(), "%u.%u.%u", &version.major, &version.minor, &version.patch);
|
||||||
|
|
||||||
|
// Only version 1.0.0 is defined currently. Eventually we may have more version, but
|
||||||
|
// some of the versions may only be valid for layers or runtimes specifically.
|
||||||
|
if (num_fields != 3 || version.major != 1 || version.minor != 0 || version.patch != 0) {
|
||||||
|
std::ostringstream error_ss;
|
||||||
|
error_ss << "ManifestFile::IsValidJson - JSON \"file_format_version\" " << version.major << "." << version.minor << "."
|
||||||
|
<< version.patch << " is not supported";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetExtensionProperties(const std::vector<ExtensionListing> &extensions, std::vector<XrExtensionProperties> &props) {
|
||||||
|
for (const auto &ext : extensions) {
|
||||||
|
auto it =
|
||||||
|
std::find_if(props.begin(), props.end(), [&](XrExtensionProperties &prop) { return prop.extensionName == ext.name; });
|
||||||
|
if (it != props.end()) {
|
||||||
|
it->extensionVersion = std::max(it->extensionVersion, ext.extension_version);
|
||||||
|
} else {
|
||||||
|
XrExtensionProperties prop = {};
|
||||||
|
prop.type = XR_TYPE_EXTENSION_PROPERTIES;
|
||||||
|
prop.next = nullptr;
|
||||||
|
strncpy(prop.extensionName, ext.name.c_str(), XR_MAX_EXTENSION_NAME_SIZE - 1);
|
||||||
|
prop.extensionName[XR_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
|
||||||
|
prop.extensionVersion = ext.extension_version;
|
||||||
|
props.push_back(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return any instance extensions found in the manifest files in the proper form for
|
||||||
|
// OpenXR (XrExtensionProperties).
|
||||||
|
void ManifestFile::GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props) {
|
||||||
|
GetExtensionProperties(_instance_extensions, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &ManifestFile::GetFunctionName(const std::string &func_name) const {
|
||||||
|
if (!_functions_renamed.empty()) {
|
||||||
|
auto found = _functions_renamed.find(func_name);
|
||||||
|
if (found != _functions_renamed.end()) {
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeManifestFile::RuntimeManifestFile(const std::string &filename, const std::string &library_path)
|
||||||
|
: ManifestFile(MANIFEST_TYPE_RUNTIME, filename, library_path) {}
|
||||||
|
|
||||||
|
static void ParseExtension(Json::Value const &ext, std::vector<ExtensionListing> &extensions) {
|
||||||
|
Json::Value ext_name = ext["name"];
|
||||||
|
Json::Value ext_version = ext["extension_version"];
|
||||||
|
|
||||||
|
// Allow "extension_version" as a String or a UInt to maintain backwards compatibility, even though it should be a String.
|
||||||
|
// Internal Issue 1411: https://gitlab.khronos.org/openxr/openxr/-/issues/1411
|
||||||
|
// Internal MR !1867: https://gitlab.khronos.org/openxr/openxr/-/merge_requests/1867
|
||||||
|
if (ext_name.isString() && (ext_version.isString() || ext_version.isUInt())) {
|
||||||
|
ExtensionListing ext_listing = {};
|
||||||
|
ext_listing.name = ext_name.asString();
|
||||||
|
if (ext_version.isUInt()) {
|
||||||
|
ext_listing.extension_version = ext_version.asUInt();
|
||||||
|
} else {
|
||||||
|
ext_listing.extension_version = atoi(ext_version.asString().c_str());
|
||||||
|
}
|
||||||
|
extensions.push_back(ext_listing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManifestFile::ParseCommon(Json::Value const &root_node) {
|
||||||
|
const Json::Value &inst_exts = root_node["instance_extensions"];
|
||||||
|
if (!inst_exts.isNull() && inst_exts.isArray()) {
|
||||||
|
for (const auto &ext : inst_exts) {
|
||||||
|
ParseExtension(ext, _instance_extensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Json::Value &funcs_renamed = root_node["functions"];
|
||||||
|
if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
|
||||||
|
for (Json::ValueConstIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
|
||||||
|
if (!(*func_it).isString()) {
|
||||||
|
LoaderLogger::LogWarningMessage(
|
||||||
|
"", "ManifestFile::ParseCommon " + _filename + " \"functions\" section contains non-string values.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string original_name = func_it.key().asString();
|
||||||
|
std::string new_name = (*func_it).asString();
|
||||||
|
_functions_renamed.emplace(original_name, new_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeManifestFile::CreateIfValid(std::string const &filename,
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
|
||||||
|
std::ifstream json_stream(filename, std::ifstream::in);
|
||||||
|
|
||||||
|
LoaderLogger::LogInfoMessage("", "RuntimeManifestFile::CreateIfValid - attempting to load " + filename);
|
||||||
|
std::ostringstream error_ss("RuntimeManifestFile::CreateIfValid ");
|
||||||
|
if (!json_stream.is_open()) {
|
||||||
|
error_ss << "failed to open " << filename << ". Does it exist?";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Json::CharReaderBuilder builder;
|
||||||
|
std::string errors;
|
||||||
|
Json::Value root_node = Json::nullValue;
|
||||||
|
if (!Json::parseFromStream(builder, json_stream, &root_node, &errors) || !root_node.isObject()) {
|
||||||
|
error_ss << "failed to parse " << filename << ".";
|
||||||
|
if (!errors.empty()) {
|
||||||
|
error_ss << " (Error message: " << errors << ")";
|
||||||
|
}
|
||||||
|
error_ss << " Is it a valid runtime manifest file?";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateIfValid(root_node, filename, manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeManifestFile::CreateIfValid(const Json::Value &root_node, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
|
||||||
|
std::ostringstream error_ss("RuntimeManifestFile::CreateIfValid ");
|
||||||
|
JsonVersion file_version = {};
|
||||||
|
if (!ManifestFile::IsValidJson(root_node, file_version)) {
|
||||||
|
error_ss << "isValidJson indicates " << filename << " is not a valid manifest file.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Json::Value &runtime_root_node = root_node["runtime"];
|
||||||
|
// The Runtime manifest file needs the "runtime" root as well as a sub-node for "library_path". If any of those aren't there,
|
||||||
|
// fail.
|
||||||
|
if (runtime_root_node.isNull() || runtime_root_node["library_path"].isNull() || !runtime_root_node["library_path"].isString()) {
|
||||||
|
error_ss << filename << " is missing required fields. Verify all proper fields exist.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string lib_path = runtime_root_node["library_path"].asString();
|
||||||
|
|
||||||
|
// If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
|
||||||
|
// global library path.
|
||||||
|
if (lib_path.find('\\') != std::string::npos || lib_path.find('/') != std::string::npos) {
|
||||||
|
// If the library_path is an absolute path, just use that if it exists
|
||||||
|
if (FileSysUtilsIsAbsolutePath(lib_path)) {
|
||||||
|
if (!FileSysUtilsPathExists(lib_path)) {
|
||||||
|
error_ss << filename << " library " << lib_path << " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, treat the library path as a relative path based on the JSON file.
|
||||||
|
std::string canonical_path;
|
||||||
|
std::string combined_path;
|
||||||
|
std::string file_parent;
|
||||||
|
// Search relative to the real manifest file, not relative to the symlink
|
||||||
|
if (!FileSysUtilsGetCanonicalPath(filename, canonical_path)) {
|
||||||
|
// Give relative to the non-canonical path a chance
|
||||||
|
canonical_path = filename;
|
||||||
|
}
|
||||||
|
if (!FileSysUtilsGetParentPath(canonical_path, file_parent) ||
|
||||||
|
!FileSysUtilsCombinePaths(file_parent, lib_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
|
||||||
|
error_ss << filename << " library " << combined_path << " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lib_path = combined_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this runtime manifest file
|
||||||
|
manifest_files.emplace_back(new RuntimeManifestFile(filename, lib_path));
|
||||||
|
|
||||||
|
// Add any extensions to it after the fact.
|
||||||
|
// Handle any renamed functions
|
||||||
|
manifest_files.back()->ParseCommon(runtime_root_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all manifest files in the appropriate search paths/registries for the given type.
|
||||||
|
XrResult RuntimeManifestFile::FindManifestFiles(std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
|
||||||
|
XrResult result = XR_SUCCESS;
|
||||||
|
std::string filename = PlatformUtilsGetSecureEnv(OPENXR_RUNTIME_JSON_ENV_VAR);
|
||||||
|
if (!filename.empty()) {
|
||||||
|
LoaderLogger::LogInfoMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - using environment variable override runtime file " + filename);
|
||||||
|
} else {
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
ReadRuntimeDataFilesInRegistry("", "ActiveRuntime", filenames);
|
||||||
|
if (filenames.size() == 0) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to find active runtime file in registry");
|
||||||
|
return XR_ERROR_RUNTIME_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
if (filenames.size() > 1) {
|
||||||
|
LoaderLogger::LogWarningMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - found too many default runtime files in registry");
|
||||||
|
}
|
||||||
|
filename = filenames[0];
|
||||||
|
LoaderLogger::LogInfoMessage("",
|
||||||
|
"RuntimeManifestFile::FindManifestFiles - using registry-specified runtime file " + filename);
|
||||||
|
#elif defined(XR_OS_LINUX)
|
||||||
|
const std::string relative_path =
|
||||||
|
"openxr/" + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + "/active_runtime.json";
|
||||||
|
if (!FindXDGConfigFile(relative_path, filename)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
|
||||||
|
return XR_ERROR_RUNTIME_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(XR_KHR_LOADER_INIT_SUPPORT)
|
||||||
|
Json::Value virtualManifest;
|
||||||
|
result = GetPlatformRuntimeVirtualManifest(virtualManifest);
|
||||||
|
if (XR_SUCCESS == result) {
|
||||||
|
RuntimeManifestFile::CreateIfValid(virtualManifest, "", manifest_files);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // defined(XR_KHR_LOADER_INIT_SUPPORT)
|
||||||
|
if (!PlatformGetGlobalRuntimeFileName(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), filename)) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
"", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
|
||||||
|
return XR_ERROR_RUNTIME_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
result = XR_SUCCESS;
|
||||||
|
LoaderLogger::LogInfoMessage("", "RuntimeManifestFile::FindManifestFiles - using global runtime file " + filename);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
RuntimeManifestFile::CreateIfValid(filename, manifest_files);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiLayerManifestFile::ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
|
||||||
|
const std::string &description, const JsonVersion &api_version,
|
||||||
|
const uint32_t &implementation_version, const std::string &library_path)
|
||||||
|
: ManifestFile(type, filename, library_path),
|
||||||
|
_api_version(api_version),
|
||||||
|
_layer_name(layer_name),
|
||||||
|
_description(description),
|
||||||
|
_implementation_version(implementation_version) {}
|
||||||
|
|
||||||
|
void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
|
||||||
|
std::ifstream json_stream(filename, std::ifstream::in);
|
||||||
|
|
||||||
|
std::ostringstream error_ss("ApiLayerManifestFile::CreateIfValid ");
|
||||||
|
if (!json_stream.is_open()) {
|
||||||
|
error_ss << "failed to open " << filename << ". Does it exist?";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::CharReaderBuilder builder;
|
||||||
|
std::string errors;
|
||||||
|
Json::Value root_node = Json::nullValue;
|
||||||
|
if (!Json::parseFromStream(builder, json_stream, &root_node, &errors) || !root_node.isObject()) {
|
||||||
|
error_ss << "failed to parse " << filename << ".";
|
||||||
|
if (!errors.empty()) {
|
||||||
|
error_ss << " (Error message: " << errors << ")";
|
||||||
|
}
|
||||||
|
error_ss << " Is it a valid layer manifest file?";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JsonVersion file_version = {};
|
||||||
|
if (!ManifestFile::IsValidJson(root_node, file_version)) {
|
||||||
|
error_ss << "isValidJson indicates " << filename << " is not a valid manifest file.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value layer_root_node = root_node["api_layer"];
|
||||||
|
|
||||||
|
// The API Layer manifest file needs the "api_layer" root as well as other sub-nodes.
|
||||||
|
// If any of those aren't there, fail.
|
||||||
|
if (layer_root_node.isNull() || layer_root_node["name"].isNull() || !layer_root_node["name"].isString() ||
|
||||||
|
layer_root_node["api_version"].isNull() || !layer_root_node["api_version"].isString() ||
|
||||||
|
layer_root_node["library_path"].isNull() || !layer_root_node["library_path"].isString() ||
|
||||||
|
layer_root_node["implementation_version"].isNull() || !layer_root_node["implementation_version"].isString()) {
|
||||||
|
error_ss << filename << " is missing required fields. Verify all proper fields exist.";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (MANIFEST_TYPE_IMPLICIT_API_LAYER == type) {
|
||||||
|
bool enabled = true;
|
||||||
|
// Implicit layers require the disable environment variable.
|
||||||
|
if (layer_root_node["disable_environment"].isNull() || !layer_root_node["disable_environment"].isString()) {
|
||||||
|
error_ss << "Implicit layer " << filename << " is missing \"disable_environment\"";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if there's an enable environment variable provided
|
||||||
|
if (!layer_root_node["enable_environment"].isNull() && layer_root_node["enable_environment"].isString()) {
|
||||||
|
std::string env_var = layer_root_node["enable_environment"].asString();
|
||||||
|
// If it's not set in the environment, disable the layer
|
||||||
|
if (!PlatformUtilsGetEnvSet(env_var.c_str())) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for the disable environment variable, which must be provided in the JSON
|
||||||
|
std::string env_var = layer_root_node["disable_environment"].asString();
|
||||||
|
// If the env var is set, disable the layer. Disable env var overrides enable above
|
||||||
|
if (PlatformUtilsGetEnvSet(env_var.c_str())) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not enabled, so pretend like it isn't even there.
|
||||||
|
if (!enabled) {
|
||||||
|
error_ss << "Implicit layer " << filename << " is disabled";
|
||||||
|
LoaderLogger::LogInfoMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string layer_name = layer_root_node["name"].asString();
|
||||||
|
std::string api_version_string = layer_root_node["api_version"].asString();
|
||||||
|
JsonVersion api_version = {};
|
||||||
|
const int num_fields = sscanf(api_version_string.c_str(), "%u.%u", &api_version.major, &api_version.minor);
|
||||||
|
api_version.patch = 0;
|
||||||
|
|
||||||
|
if ((num_fields != 2) || (api_version.major == 0 && api_version.minor == 0) ||
|
||||||
|
api_version.major > XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) {
|
||||||
|
error_ss << "layer " << filename << " has invalid API Version. Skipping layer.";
|
||||||
|
LoaderLogger::LogWarningMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t implementation_version = atoi(layer_root_node["implementation_version"].asString().c_str());
|
||||||
|
std::string library_path = layer_root_node["library_path"].asString();
|
||||||
|
|
||||||
|
// If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
|
||||||
|
// global library path.
|
||||||
|
if (library_path.find('\\') != std::string::npos || library_path.find('/') != std::string::npos) {
|
||||||
|
// If the library_path is an absolute path, just use that if it exists
|
||||||
|
if (FileSysUtilsIsAbsolutePath(library_path)) {
|
||||||
|
if (!FileSysUtilsPathExists(library_path)) {
|
||||||
|
error_ss << filename << " library " << library_path << " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, treat the library path as a relative path based on the JSON file.
|
||||||
|
std::string combined_path;
|
||||||
|
std::string file_parent;
|
||||||
|
if (!FileSysUtilsGetParentPath(filename, file_parent) ||
|
||||||
|
!FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
|
||||||
|
error_ss << filename << " library " << combined_path << " does not appear to exist";
|
||||||
|
LoaderLogger::LogErrorMessage("", error_ss.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
library_path = combined_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string description;
|
||||||
|
if (!layer_root_node["description"].isNull() && layer_root_node["description"].isString()) {
|
||||||
|
description = layer_root_node["description"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this layer manifest file
|
||||||
|
manifest_files.emplace_back(
|
||||||
|
new ApiLayerManifestFile(type, filename, layer_name, description, api_version, implementation_version, library_path));
|
||||||
|
|
||||||
|
// Add any extensions to it after the fact.
|
||||||
|
manifest_files.back()->ParseCommon(layer_root_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiLayerManifestFile::PopulateApiLayerProperties(XrApiLayerProperties &props) const {
|
||||||
|
props.layerVersion = _implementation_version;
|
||||||
|
props.specVersion = XR_MAKE_VERSION(_api_version.major, _api_version.minor, _api_version.patch);
|
||||||
|
strncpy(props.layerName, _layer_name.c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
|
||||||
|
if (_layer_name.size() >= XR_MAX_API_LAYER_NAME_SIZE - 1) {
|
||||||
|
props.layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
|
||||||
|
}
|
||||||
|
strncpy(props.description, _description.c_str(), XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1);
|
||||||
|
if (_description.size() >= XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1) {
|
||||||
|
props.description[XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all layer manifest files in the appropriate search paths/registries for the given type.
|
||||||
|
XrResult ApiLayerManifestFile::FindManifestFiles(ManifestFileType type,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
|
||||||
|
std::string relative_path;
|
||||||
|
std::string override_env_var;
|
||||||
|
std::string registry_location;
|
||||||
|
|
||||||
|
// Add the appropriate top-level folders for the relative path. These should be
|
||||||
|
// the string "openxr/" followed by the API major version as a string.
|
||||||
|
relative_path = OPENXR_RELATIVE_PATH;
|
||||||
|
relative_path += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MANIFEST_TYPE_IMPLICIT_API_LAYER:
|
||||||
|
relative_path += OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH;
|
||||||
|
override_env_var = "";
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
registry_location = OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case MANIFEST_TYPE_EXPLICIT_API_LAYER:
|
||||||
|
relative_path += OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH;
|
||||||
|
override_env_var = OPENXR_API_LAYER_PATH_ENV_VAR;
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
registry_location = OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LoaderLogger::LogErrorMessage("", "ApiLayerManifestFile::FindManifestFiles - unknown manifest file requested");
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool override_active = false;
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
ReadDataFilesInSearchPaths(override_env_var, relative_path, override_active, filenames);
|
||||||
|
|
||||||
|
#ifdef XR_OS_WINDOWS
|
||||||
|
// Read the registry if the override wasn't active.
|
||||||
|
if (!override_active) {
|
||||||
|
ReadLayerDataFilesInRegistry(registry_location, filenames);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (std::string &cur_file : filenames) {
|
||||||
|
ApiLayerManifestFile::CreateIfValid(type, cur_file, manifest_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
103
thirdparty/openxr/src/loader/manifest_file.hpp
vendored
Normal file
103
thirdparty/openxr/src/loader/manifest_file.hpp
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (c) 2017 The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017 Valve Corporation
|
||||||
|
// Copyright (c) 2017 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ManifestFileType {
|
||||||
|
MANIFEST_TYPE_UNDEFINED = 0,
|
||||||
|
MANIFEST_TYPE_RUNTIME,
|
||||||
|
MANIFEST_TYPE_IMPLICIT_API_LAYER,
|
||||||
|
MANIFEST_TYPE_EXPLICIT_API_LAYER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JsonVersion {
|
||||||
|
uint32_t major;
|
||||||
|
uint32_t minor;
|
||||||
|
uint32_t patch;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExtensionListing {
|
||||||
|
std::string name;
|
||||||
|
uint32_t extension_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ManifestFile class -
|
||||||
|
// Base class responsible for finding and parsing manifest files.
|
||||||
|
class ManifestFile {
|
||||||
|
public:
|
||||||
|
// Non-copyable
|
||||||
|
ManifestFile(const ManifestFile &) = delete;
|
||||||
|
ManifestFile &operator=(const ManifestFile &) = delete;
|
||||||
|
|
||||||
|
ManifestFileType Type() const { return _type; }
|
||||||
|
const std::string &Filename() const { return _filename; }
|
||||||
|
const std::string &LibraryPath() const { return _library_path; }
|
||||||
|
void GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props);
|
||||||
|
const std::string &GetFunctionName(const std::string &func_name) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path);
|
||||||
|
void ParseCommon(Json::Value const &root_node);
|
||||||
|
static bool IsValidJson(const Json::Value &root, JsonVersion &version);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _filename;
|
||||||
|
ManifestFileType _type;
|
||||||
|
std::string _library_path;
|
||||||
|
std::vector<ExtensionListing> _instance_extensions;
|
||||||
|
std::unordered_map<std::string, std::string> _functions_renamed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// RuntimeManifestFile class -
|
||||||
|
// Responsible for finding and parsing Runtime-specific manifest files.
|
||||||
|
class RuntimeManifestFile : public ManifestFile {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult FindManifestFiles(std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RuntimeManifestFile(const std::string &filename, const std::string &library_path);
|
||||||
|
static void CreateIfValid(const std::string &filename, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
|
||||||
|
static void CreateIfValid(const Json::Value &root_node, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ApiLayerManifestFile class -
|
||||||
|
// Responsible for finding and parsing API Layer-specific manifest files.
|
||||||
|
class ApiLayerManifestFile : public ManifestFile {
|
||||||
|
public:
|
||||||
|
// Factory method
|
||||||
|
static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
const std::string &LayerName() const { return _layer_name; }
|
||||||
|
void PopulateApiLayerProperties(XrApiLayerProperties &props) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
|
||||||
|
const std::string &description, const JsonVersion &api_version, const uint32_t &implementation_version,
|
||||||
|
const std::string &library_path);
|
||||||
|
static void CreateIfValid(ManifestFileType type, const std::string &filename,
|
||||||
|
std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
|
||||||
|
|
||||||
|
JsonVersion _api_version;
|
||||||
|
std::string _layer_name;
|
||||||
|
std::string _description;
|
||||||
|
uint32_t _implementation_version;
|
||||||
|
};
|
||||||
493
thirdparty/openxr/src/loader/runtime_interface.cpp
vendored
Normal file
493
thirdparty/openxr/src/loader/runtime_interface.cpp
vendored
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
|
||||||
|
#include "manifest_file.hpp"
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
#include "android_utilities.h"
|
||||||
|
#include <json/value.h>
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
namespace {
|
||||||
|
/*!
|
||||||
|
* Stores a copy of the data passed to the xrInitializeLoaderKHR function in a singleton.
|
||||||
|
*/
|
||||||
|
class LoaderInitData {
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* Singleton accessor.
|
||||||
|
*/
|
||||||
|
static LoaderInitData& instance() {
|
||||||
|
static LoaderInitData obj;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
/*!
|
||||||
|
* Type alias for the platform-specific structure type.
|
||||||
|
*/
|
||||||
|
using StructType = XrLoaderInitInfoAndroidKHR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get our copy of the data, casted to pass to the runtime's matching method.
|
||||||
|
*/
|
||||||
|
const XrLoaderInitInfoBaseHeaderKHR* getParam() const { return reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(&_data); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Get the data via its real structure type.
|
||||||
|
*/
|
||||||
|
const StructType& getData() const { return _data; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Has this been correctly initialized?
|
||||||
|
*/
|
||||||
|
bool initialized() const noexcept { return _initialized; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Initialize loader data - called by InitializeLoader() and thus ultimately by the loader's xrInitializeLoaderKHR
|
||||||
|
* implementation. Each platform that needs this extension will provide an implementation of this.
|
||||||
|
*/
|
||||||
|
XrResult initialize(const XrLoaderInitInfoBaseHeaderKHR* info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Private constructor, forces use of singleton accessor.
|
||||||
|
LoaderInitData() = default;
|
||||||
|
//! Platform-specific init data
|
||||||
|
StructType _data = {};
|
||||||
|
//! Flag for indicating whether _data is valid.
|
||||||
|
bool _initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
// Check and copy the Android-specific init data.
|
||||||
|
XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) {
|
||||||
|
if (info->type != XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
auto cast_info = reinterpret_cast<XrLoaderInitInfoAndroidKHR const*>(info);
|
||||||
|
|
||||||
|
if (cast_info->applicationVM == nullptr) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
if (cast_info->applicationContext == nullptr) {
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
_data = *cast_info;
|
||||||
|
jni::init((jni::JavaVM*)_data.applicationVM);
|
||||||
|
_data.next = nullptr;
|
||||||
|
_initialized = true;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) {
|
||||||
|
return LoaderInitData::instance().initialize(loaderInitInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest) {
|
||||||
|
using wrap::android::content::Context;
|
||||||
|
auto& initData = LoaderInitData::instance();
|
||||||
|
if (!initData.initialized()) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
auto context = Context(reinterpret_cast<jobject>(initData.getData().applicationContext));
|
||||||
|
if (context.isNull()) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
Json::Value virtualManifest;
|
||||||
|
if (0 != openxr_android::getActiveRuntimeVirtualManifest(context, virtualManifest)) {
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
out_manifest = virtualManifest;
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif // XR_USE_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::TryLoadingSingleRuntime(const std::string& openxr_command,
|
||||||
|
std::unique_ptr<RuntimeManifestFile>& manifest_file) {
|
||||||
|
LoaderPlatformLibraryHandle runtime_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
|
||||||
|
if (nullptr == runtime_library) {
|
||||||
|
std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
|
||||||
|
std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
warning_message += manifest_file->Filename();
|
||||||
|
warning_message += ", failed to load with message \"";
|
||||||
|
warning_message += library_message;
|
||||||
|
warning_message += "\"";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, warning_message);
|
||||||
|
return XR_ERROR_FILE_ACCESS_ERROR;
|
||||||
|
}
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
if (!LoaderInitData::instance().initialized()) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntime skipping manifest file " +
|
||||||
|
manifest_file->Filename() +
|
||||||
|
" because xrInitializeLoaderKHR was not yet called.");
|
||||||
|
|
||||||
|
LoaderPlatformLibraryClose(runtime_library);
|
||||||
|
return XR_ERROR_VALIDATION_FAILURE;
|
||||||
|
}
|
||||||
|
bool forwardedInitLoader = false;
|
||||||
|
{
|
||||||
|
// If we have xrInitializeLoaderKHR exposed as an export, forward call to it.
|
||||||
|
const auto function_name = manifest_file->GetFunctionName("xrInitializeLoaderKHR");
|
||||||
|
auto initLoader =
|
||||||
|
reinterpret_cast<PFN_xrInitializeLoaderKHR>(LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
|
||||||
|
if (initLoader != nullptr) {
|
||||||
|
// we found the entry point one way or another.
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command,
|
||||||
|
"RuntimeInterface::LoadRuntime forwarding xrInitializeLoaderKHR call to runtime before "
|
||||||
|
"calling xrNegotiateLoaderRuntimeInterface.");
|
||||||
|
XrResult res = initLoader(LoaderInitData::instance().getParam());
|
||||||
|
if (!XR_SUCCEEDED(res)) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"RuntimeInterface::LoadRuntime forwarded call to xrInitializeLoaderKHR failed.");
|
||||||
|
|
||||||
|
LoaderPlatformLibraryClose(runtime_library);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
forwardedInitLoader = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get and settle on an runtime interface version (using any provided name if required).
|
||||||
|
std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderRuntimeInterface");
|
||||||
|
auto negotiate =
|
||||||
|
reinterpret_cast<PFN_xrNegotiateLoaderRuntimeInterface>(LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
|
||||||
|
|
||||||
|
// Loader info for negotiation
|
||||||
|
XrNegotiateLoaderInfo loader_info = {};
|
||||||
|
loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
|
||||||
|
loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
|
||||||
|
loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
|
||||||
|
loader_info.minInterfaceVersion = 1;
|
||||||
|
loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION;
|
||||||
|
loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
|
||||||
|
loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
|
||||||
|
|
||||||
|
// Set up the runtime return structure
|
||||||
|
XrNegotiateRuntimeRequest runtime_info = {};
|
||||||
|
runtime_info.structType = XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST;
|
||||||
|
runtime_info.structVersion = XR_RUNTIME_INFO_STRUCT_VERSION;
|
||||||
|
runtime_info.structSize = sizeof(XrNegotiateRuntimeRequest);
|
||||||
|
|
||||||
|
// Skip calling the negotiate function and fail if the function pointer
|
||||||
|
// could not get loaded
|
||||||
|
XrResult res = XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
if (nullptr != negotiate) {
|
||||||
|
res = negotiate(&loader_info, &runtime_info);
|
||||||
|
}
|
||||||
|
// If we supposedly succeeded, but got a nullptr for GetInstanceProcAddr
|
||||||
|
// then something still went wrong, so return with an error.
|
||||||
|
if (XR_SUCCEEDED(res)) {
|
||||||
|
uint32_t runtime_major = XR_VERSION_MAJOR(runtime_info.runtimeApiVersion);
|
||||||
|
uint32_t runtime_minor = XR_VERSION_MINOR(runtime_info.runtimeApiVersion);
|
||||||
|
uint32_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION);
|
||||||
|
if (nullptr == runtime_info.getInstanceProcAddr) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", negotiation succeeded but returned NULL getInstanceProcAddr";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
} else if (0 >= runtime_info.runtimeInterfaceVersion ||
|
||||||
|
XR_CURRENT_LOADER_RUNTIME_VERSION < runtime_info.runtimeInterfaceVersion) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", negotiation succeeded but returned invalid interface version";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
} else if (runtime_major != loader_major || (runtime_major == 0 && runtime_minor == 0)) {
|
||||||
|
std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
error_message += manifest_file->Filename();
|
||||||
|
error_message += ", OpenXR version returned not compatible with this loader";
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, error_message);
|
||||||
|
res = XR_ERROR_FILE_CONTENTS_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
if (XR_SUCCEEDED(res) && !forwardedInitLoader) {
|
||||||
|
// Forward initialize loader call, where possible and if we did not do so before.
|
||||||
|
PFN_xrVoidFunction initializeVoid = nullptr;
|
||||||
|
PFN_xrInitializeLoaderKHR initialize = nullptr;
|
||||||
|
|
||||||
|
// Now we may try asking xrGetInstanceProcAddr
|
||||||
|
if (XR_SUCCEEDED(runtime_info.getInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", &initializeVoid))) {
|
||||||
|
if (initializeVoid == nullptr) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"RuntimeInterface::LoadRuntime got success from xrGetInstanceProcAddr "
|
||||||
|
"for xrInitializeLoaderKHR, but output a null pointer.");
|
||||||
|
res = XR_ERROR_RUNTIME_FAILURE;
|
||||||
|
} else {
|
||||||
|
initialize = reinterpret_cast<PFN_xrInitializeLoaderKHR>(initializeVoid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initialize != nullptr) {
|
||||||
|
// we found the entry point one way or another.
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command,
|
||||||
|
"RuntimeInterface::LoadRuntime forwarding xrInitializeLoaderKHR call to runtime after "
|
||||||
|
"calling xrNegotiateLoaderRuntimeInterface.");
|
||||||
|
res = initialize(LoaderInitData::instance().getParam());
|
||||||
|
if (!XR_SUCCEEDED(res)) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command,
|
||||||
|
"RuntimeInterface::LoadRuntime forwarded call to xrInitializeLoaderKHR failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (XR_FAILED(res)) {
|
||||||
|
std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
|
||||||
|
warning_message += manifest_file->Filename();
|
||||||
|
warning_message += ", negotiation failed with error ";
|
||||||
|
warning_message += std::to_string(res);
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, warning_message);
|
||||||
|
LoaderPlatformLibraryClose(runtime_library);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string info_message = "RuntimeInterface::LoadRuntime succeeded loading runtime defined in manifest file ";
|
||||||
|
info_message += manifest_file->Filename();
|
||||||
|
info_message += " using interface version ";
|
||||||
|
info_message += std::to_string(runtime_info.runtimeInterfaceVersion);
|
||||||
|
info_message += " and OpenXR API version ";
|
||||||
|
info_message += std::to_string(XR_VERSION_MAJOR(runtime_info.runtimeApiVersion));
|
||||||
|
info_message += ".";
|
||||||
|
info_message += std::to_string(XR_VERSION_MINOR(runtime_info.runtimeApiVersion));
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, info_message);
|
||||||
|
|
||||||
|
// Use this runtime
|
||||||
|
GetInstance().reset(new RuntimeInterface(runtime_library, runtime_info.getInstanceProcAddr));
|
||||||
|
|
||||||
|
// Grab the list of extensions this runtime supports for easy filtering after the
|
||||||
|
// xrCreateInstance call
|
||||||
|
std::vector<std::string> supported_extensions;
|
||||||
|
std::vector<XrExtensionProperties> extension_properties;
|
||||||
|
GetInstance()->GetInstanceExtensionProperties(extension_properties);
|
||||||
|
supported_extensions.reserve(extension_properties.size());
|
||||||
|
for (XrExtensionProperties ext_prop : extension_properties) {
|
||||||
|
supported_extensions.emplace_back(ext_prop.extensionName);
|
||||||
|
}
|
||||||
|
GetInstance()->SetSupportedExtensions(supported_extensions);
|
||||||
|
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::LoadRuntime(const std::string& openxr_command) {
|
||||||
|
// If something's already loaded, we're done here.
|
||||||
|
if (GetInstance() != nullptr) {
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
|
||||||
|
if (!LoaderInitData::instance().initialized()) {
|
||||||
|
LoaderLogger::LogErrorMessage(
|
||||||
|
openxr_command, "RuntimeInterface::LoadRuntime cannot run because xrInitializeLoaderKHR was not successfully called.");
|
||||||
|
return XR_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
#endif // XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RuntimeManifestFile>> runtime_manifest_files = {};
|
||||||
|
|
||||||
|
// Find the available runtimes which we may need to report information for.
|
||||||
|
XrResult last_error = RuntimeManifestFile::FindManifestFiles(runtime_manifest_files);
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - unknown error");
|
||||||
|
} else {
|
||||||
|
last_error = XR_ERROR_RUNTIME_UNAVAILABLE;
|
||||||
|
for (std::unique_ptr<RuntimeManifestFile>& manifest_file : runtime_manifest_files) {
|
||||||
|
last_error = RuntimeInterface::TryLoadingSingleRuntime(openxr_command, manifest_file);
|
||||||
|
if (XR_SUCCEEDED(last_error)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsuccessful in loading any runtime, throw the runtime unavailable message.
|
||||||
|
if (XR_FAILED(last_error)) {
|
||||||
|
LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - failed to load a runtime");
|
||||||
|
last_error = XR_ERROR_RUNTIME_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::UnloadRuntime(const std::string& openxr_command) {
|
||||||
|
if (GetInstance()) {
|
||||||
|
LoaderLogger::LogInfoMessage(openxr_command, "RuntimeInterface::UnloadRuntime - Unloading RuntimeInterface");
|
||||||
|
GetInstance().reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function) {
|
||||||
|
return GetInstance()->_get_instance_proc_addr(instance, name, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance instance) {
|
||||||
|
XrGeneratedDispatchTable* table = nullptr;
|
||||||
|
std::lock_guard<std::mutex> mlock(GetInstance()->_dispatch_table_mutex);
|
||||||
|
auto it = GetInstance()->_dispatch_table_map.find(instance);
|
||||||
|
if (it != GetInstance()->_dispatch_table_map.end()) {
|
||||||
|
table = it->second.get();
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XrGeneratedDispatchTable* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
XrInstance runtime_instance = XR_NULL_HANDLE;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(GetInstance()->_messenger_to_instance_mutex);
|
||||||
|
auto it = GetInstance()->_messenger_to_instance_map.find(messenger);
|
||||||
|
if (it != GetInstance()->_messenger_to_instance_map.end()) {
|
||||||
|
runtime_instance = it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetDispatchTable(runtime_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeInterface::RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instance_proc_addr)
|
||||||
|
: _runtime_library(runtime_library), _get_instance_proc_addr(get_instance_proc_addr) {}
|
||||||
|
|
||||||
|
RuntimeInterface::~RuntimeInterface() {
|
||||||
|
std::string info_message = "RuntimeInterface being destroyed.";
|
||||||
|
LoaderLogger::LogInfoMessage("", info_message);
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
_dispatch_table_map.clear();
|
||||||
|
}
|
||||||
|
LoaderPlatformLibraryClose(_runtime_library);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties) {
|
||||||
|
std::vector<XrExtensionProperties> runtime_extension_properties;
|
||||||
|
PFN_xrEnumerateInstanceExtensionProperties rt_xrEnumerateInstanceExtensionProperties;
|
||||||
|
_get_instance_proc_addr(XR_NULL_HANDLE, "xrEnumerateInstanceExtensionProperties",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrEnumerateInstanceExtensionProperties));
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t count_output = 0;
|
||||||
|
// Get the count from the runtime
|
||||||
|
rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, nullptr);
|
||||||
|
if (count_output > 0) {
|
||||||
|
runtime_extension_properties.resize(count_output);
|
||||||
|
count = count_output;
|
||||||
|
for (XrExtensionProperties& ext_prop : runtime_extension_properties) {
|
||||||
|
ext_prop.type = XR_TYPE_EXTENSION_PROPERTIES;
|
||||||
|
ext_prop.next = nullptr;
|
||||||
|
}
|
||||||
|
rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, runtime_extension_properties.data());
|
||||||
|
}
|
||||||
|
size_t ext_count = runtime_extension_properties.size();
|
||||||
|
size_t props_count = extension_properties.size();
|
||||||
|
for (size_t ext = 0; ext < ext_count; ++ext) {
|
||||||
|
bool found = false;
|
||||||
|
for (size_t prop = 0; prop < props_count; ++prop) {
|
||||||
|
// If we find it, then make sure the spec version matches that of the runtime instead of the
|
||||||
|
// layer.
|
||||||
|
if (strcmp(extension_properties[prop].extensionName, runtime_extension_properties[ext].extensionName) == 0) {
|
||||||
|
// Make sure the spec version used is the runtime's
|
||||||
|
extension_properties[prop].extensionVersion = runtime_extension_properties[ext].extensionVersion;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
extension_properties.push_back(runtime_extension_properties[ext]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance) {
|
||||||
|
XrResult res = XR_SUCCESS;
|
||||||
|
bool create_succeeded = false;
|
||||||
|
PFN_xrCreateInstance rt_xrCreateInstance;
|
||||||
|
_get_instance_proc_addr(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrCreateInstance));
|
||||||
|
res = rt_xrCreateInstance(info, instance);
|
||||||
|
if (XR_SUCCEEDED(res)) {
|
||||||
|
create_succeeded = true;
|
||||||
|
std::unique_ptr<XrGeneratedDispatchTable> dispatch_table(new XrGeneratedDispatchTable());
|
||||||
|
GeneratedXrPopulateDispatchTable(dispatch_table.get(), *instance, _get_instance_proc_addr);
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
_dispatch_table_map[*instance] = std::move(dispatch_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the failure occurred during the populate, clean up the instance we had picked up from the runtime
|
||||||
|
if (XR_FAILED(res) && create_succeeded) {
|
||||||
|
PFN_xrDestroyInstance rt_xrDestroyInstance;
|
||||||
|
_get_instance_proc_addr(*instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
|
||||||
|
rt_xrDestroyInstance(*instance);
|
||||||
|
*instance = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrResult RuntimeInterface::DestroyInstance(XrInstance instance) {
|
||||||
|
if (XR_NULL_HANDLE != instance) {
|
||||||
|
// Destroy the dispatch table for this instance first
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
|
||||||
|
auto map_iter = _dispatch_table_map.find(instance);
|
||||||
|
if (map_iter != _dispatch_table_map.end()) {
|
||||||
|
_dispatch_table_map.erase(map_iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now delete the instance
|
||||||
|
PFN_xrDestroyInstance rt_xrDestroyInstance;
|
||||||
|
_get_instance_proc_addr(instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
|
||||||
|
rt_xrDestroyInstance(instance);
|
||||||
|
}
|
||||||
|
return XR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeInterface::TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
|
||||||
|
_messenger_to_instance_map[messenger] = instance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger) {
|
||||||
|
if (XR_NULL_HANDLE != messenger) {
|
||||||
|
std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
|
||||||
|
_messenger_to_instance_map.erase(messenger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeInterface::SetSupportedExtensions(std::vector<std::string>& supported_extensions) {
|
||||||
|
_supported_extensions = supported_extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeInterface::SupportsExtension(const std::string& extension_name) {
|
||||||
|
bool found_prop = false;
|
||||||
|
for (const std::string& supported_extension : _supported_extensions) {
|
||||||
|
if (supported_extension == extension_name) {
|
||||||
|
found_prop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_prop;
|
||||||
|
}
|
||||||
84
thirdparty/openxr/src/loader/runtime_interface.hpp
vendored
Normal file
84
thirdparty/openxr/src/loader/runtime_interface.hpp
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
//
|
||||||
|
// Initial Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#ifdef XR_USE_PLATFORM_ANDROID
|
||||||
|
#define XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XR_KHR_LOADER_INIT_SUPPORT
|
||||||
|
//! Initialize loader, where required.
|
||||||
|
XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo);
|
||||||
|
XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class RuntimeManifestFile;
|
||||||
|
struct XrGeneratedDispatchTable;
|
||||||
|
|
||||||
|
class RuntimeInterface {
|
||||||
|
public:
|
||||||
|
virtual ~RuntimeInterface();
|
||||||
|
|
||||||
|
// Helper functions for loading and unloading the runtime (but only when necessary)
|
||||||
|
static XrResult LoadRuntime(const std::string& openxr_command);
|
||||||
|
static void UnloadRuntime(const std::string& openxr_command);
|
||||||
|
static RuntimeInterface& GetRuntime() { return *(GetInstance().get()); }
|
||||||
|
static XrResult GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
|
||||||
|
|
||||||
|
// Get the direct dispatch table to this runtime, without API layers or loader terminators.
|
||||||
|
static const XrGeneratedDispatchTable* GetDispatchTable(XrInstance instance);
|
||||||
|
static const XrGeneratedDispatchTable* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
|
||||||
|
void GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties);
|
||||||
|
bool SupportsExtension(const std::string& extension_name);
|
||||||
|
XrResult CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance);
|
||||||
|
XrResult DestroyInstance(XrInstance instance);
|
||||||
|
bool TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger);
|
||||||
|
void ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger);
|
||||||
|
|
||||||
|
// No default construction
|
||||||
|
RuntimeInterface() = delete;
|
||||||
|
|
||||||
|
// Non-copyable
|
||||||
|
RuntimeInterface(const RuntimeInterface&) = delete;
|
||||||
|
RuntimeInterface& operator=(const RuntimeInterface&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instance_proc_addr);
|
||||||
|
void SetSupportedExtensions(std::vector<std::string>& supported_extensions);
|
||||||
|
static XrResult TryLoadingSingleRuntime(const std::string& openxr_command, std::unique_ptr<RuntimeManifestFile>& manifest_file);
|
||||||
|
|
||||||
|
static std::unique_ptr<RuntimeInterface>& GetInstance() {
|
||||||
|
static std::unique_ptr<RuntimeInterface> instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoaderPlatformLibraryHandle _runtime_library;
|
||||||
|
PFN_xrGetInstanceProcAddr _get_instance_proc_addr;
|
||||||
|
std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTable>> _dispatch_table_map;
|
||||||
|
std::mutex _dispatch_table_mutex;
|
||||||
|
std::unordered_map<XrDebugUtilsMessengerEXT, XrInstance> _messenger_to_instance_map;
|
||||||
|
std::mutex _messenger_to_instance_mutex;
|
||||||
|
std::vector<std::string> _supported_extensions;
|
||||||
|
};
|
||||||
700
thirdparty/openxr/src/loader/xr_generated_loader.cpp
vendored
Normal file
700
thirdparty/openxr/src/loader/xr_generated_loader.cpp
vendored
Normal file
@@ -0,0 +1,700 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See loader_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "xr_generated_loader.hpp"
|
||||||
|
|
||||||
|
#include "api_layer_interface.hpp"
|
||||||
|
#include "exception_handling.hpp"
|
||||||
|
#include "hex_and_handles.h"
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
#include "loader_logger.hpp"
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
#include "runtime_interface.hpp"
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
// Automatically generated instance trampolines and terminators
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrInstanceProperties* instanceProperties) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInstanceProperties");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetInstanceProperties(instance, instanceProperties);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
|
||||||
|
XrInstance instance,
|
||||||
|
XrEventDataBuffer* eventData) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrPollEvent");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->PollEvent(instance, eventData);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrResult value,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrResultToString");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->ResultToString(instance, value, buffer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrStructureType value,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStructureTypeToString");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->StructureTypeToString(instance, value, buffer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSystemGetInfo* getInfo,
|
||||||
|
XrSystemId* systemId) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetSystem");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetSystem(instance, getInfo, systemId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrSystemProperties* properties) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetSystemProperties");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetSystemProperties(instance, systemId, properties);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t environmentBlendModeCapacityInput,
|
||||||
|
uint32_t* environmentBlendModeCountOutput,
|
||||||
|
XrEnvironmentBlendMode* environmentBlendModes) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateEnvironmentBlendModes");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSessionCreateInfo* createInfo,
|
||||||
|
XrSession* session) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateSession");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateSession(instance, createInfo, session);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
|
||||||
|
XrSession session) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySession");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->DestroySession(session);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
|
||||||
|
XrSession session,
|
||||||
|
uint32_t spaceCapacityInput,
|
||||||
|
uint32_t* spaceCountOutput,
|
||||||
|
XrReferenceSpaceType* spaces) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateReferenceSpaces");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
|
||||||
|
XrSession session,
|
||||||
|
const XrReferenceSpaceCreateInfo* createInfo,
|
||||||
|
XrSpace* space) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateReferenceSpace");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateReferenceSpace(session, createInfo, space);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
|
||||||
|
XrSession session,
|
||||||
|
XrReferenceSpaceType referenceSpaceType,
|
||||||
|
XrExtent2Df* bounds) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetReferenceSpaceBoundsRect");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionSpaceCreateInfo* createInfo,
|
||||||
|
XrSpace* space) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateActionSpace");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateActionSpace(session, createInfo, space);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
|
||||||
|
XrSpace space,
|
||||||
|
XrSpace baseSpace,
|
||||||
|
XrTime time,
|
||||||
|
XrSpaceLocation* location) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrLocateSpace");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->LocateSpace(space, baseSpace, time, location);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
|
||||||
|
XrSpace space) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySpace");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->DestroySpace(space);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t viewConfigurationTypeCapacityInput,
|
||||||
|
uint32_t* viewConfigurationTypeCountOutput,
|
||||||
|
XrViewConfigurationType* viewConfigurationTypes) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateViewConfigurations");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
XrViewConfigurationProperties* configurationProperties) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetViewConfigurationProperties");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t viewCapacityInput,
|
||||||
|
uint32_t* viewCountOutput,
|
||||||
|
XrViewConfigurationView* views) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateViewConfigurationViews");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
|
||||||
|
XrSession session,
|
||||||
|
uint32_t formatCapacityInput,
|
||||||
|
uint32_t* formatCountOutput,
|
||||||
|
int64_t* formats) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateSwapchainFormats");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
|
||||||
|
XrSession session,
|
||||||
|
const XrSwapchainCreateInfo* createInfo,
|
||||||
|
XrSwapchain* swapchain) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateSwapchain");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateSwapchain(session, createInfo, swapchain);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
|
||||||
|
XrSwapchain swapchain) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySwapchain");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->DestroySwapchain(swapchain);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
uint32_t imageCapacityInput,
|
||||||
|
uint32_t* imageCountOutput,
|
||||||
|
XrSwapchainImageBaseHeader* images) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateSwapchainImages");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageAcquireInfo* acquireInfo,
|
||||||
|
uint32_t* index) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrAcquireSwapchainImage");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->AcquireSwapchainImage(swapchain, acquireInfo, index);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageWaitInfo* waitInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrWaitSwapchainImage");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->WaitSwapchainImage(swapchain, waitInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageReleaseInfo* releaseInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrReleaseSwapchainImage");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->ReleaseSwapchainImage(swapchain, releaseInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
|
||||||
|
XrSession session,
|
||||||
|
const XrSessionBeginInfo* beginInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrBeginSession");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->BeginSession(session, beginInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
|
||||||
|
XrSession session) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEndSession");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EndSession(session);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
|
||||||
|
XrSession session) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrRequestExitSession");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->RequestExitSession(session);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameWaitInfo* frameWaitInfo,
|
||||||
|
XrFrameState* frameState) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrWaitFrame");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->WaitFrame(session, frameWaitInfo, frameState);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameBeginInfo* frameBeginInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrBeginFrame");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->BeginFrame(session, frameBeginInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameEndInfo* frameEndInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEndFrame");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EndFrame(session, frameEndInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
|
||||||
|
XrSession session,
|
||||||
|
const XrViewLocateInfo* viewLocateInfo,
|
||||||
|
XrViewState* viewState,
|
||||||
|
uint32_t viewCapacityInput,
|
||||||
|
uint32_t* viewCountOutput,
|
||||||
|
XrView* views) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrLocateViews");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->LocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* pathString,
|
||||||
|
XrPath* path) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStringToPath");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->StringToPath(instance, pathString, path);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrPath path,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrPathToString");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->PathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrActionSetCreateInfo* createInfo,
|
||||||
|
XrActionSet* actionSet) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateActionSet");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateActionSet(instance, createInfo, actionSet);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
|
||||||
|
XrActionSet actionSet) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyActionSet");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->DestroyActionSet(actionSet);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
|
||||||
|
XrActionSet actionSet,
|
||||||
|
const XrActionCreateInfo* createInfo,
|
||||||
|
XrAction* action) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateAction");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->CreateAction(actionSet, createInfo, action);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
|
||||||
|
XrAction action) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyAction");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->DestroyAction(action);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrInteractionProfileSuggestedBinding* suggestedBindings) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSuggestInteractionProfileBindings");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->SuggestInteractionProfileBindings(instance, suggestedBindings);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
|
||||||
|
XrSession session,
|
||||||
|
const XrSessionActionSetsAttachInfo* attachInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrAttachSessionActionSets");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->AttachSessionActionSets(session, attachInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
|
||||||
|
XrSession session,
|
||||||
|
XrPath topLevelUserPath,
|
||||||
|
XrInteractionProfileState* interactionProfile) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetCurrentInteractionProfile");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateBoolean* state) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateBoolean");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetActionStateBoolean(session, getInfo, state);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateFloat* state) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateFloat");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetActionStateFloat(session, getInfo, state);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateVector2f* state) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateVector2f");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetActionStateVector2f(session, getInfo, state);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStatePose* state) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStatePose");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetActionStatePose(session, getInfo, state);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionsSyncInfo* syncInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSyncActions");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->SyncActions(session, syncInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
|
||||||
|
XrSession session,
|
||||||
|
const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
|
||||||
|
uint32_t sourceCapacityInput,
|
||||||
|
uint32_t* sourceCountOutput,
|
||||||
|
XrPath* sources) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateBoundSourcesForAction");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->EnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
|
||||||
|
XrSession session,
|
||||||
|
const XrInputSourceLocalizedNameGetInfo* getInfo,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInputSourceLocalizedName");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->GetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
|
||||||
|
XrSession session,
|
||||||
|
const XrHapticActionInfo* hapticActionInfo,
|
||||||
|
const XrHapticBaseHeader* hapticFeedback) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrApplyHapticFeedback");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->ApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
|
||||||
|
XrSession session,
|
||||||
|
const XrHapticActionInfo* hapticActionInfo) XRLOADER_ABI_TRY {
|
||||||
|
LoaderInstance* loader_instance;
|
||||||
|
XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStopHapticFeedback");
|
||||||
|
if (XR_SUCCEEDED(result)) {
|
||||||
|
result = loader_instance->DispatchTable()->StopHapticFeedback(session, hapticActionInfo);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
XRLOADER_ABI_CATCH_FALLBACK
|
||||||
|
|
||||||
|
|
||||||
252
thirdparty/openxr/src/loader/xr_generated_loader.hpp
vendored
Normal file
252
thirdparty/openxr/src/loader/xr_generated_loader.hpp
vendored
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See loader_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include "openxr/openxr.h"
|
||||||
|
#include "openxr/openxr_platform.h"
|
||||||
|
|
||||||
|
#include "loader_interfaces.h"
|
||||||
|
|
||||||
|
#include "loader_instance.hpp"
|
||||||
|
|
||||||
|
#include "loader_platform.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loader manually generated function prototypes
|
||||||
|
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrInstanceProperties* instanceProperties);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
|
||||||
|
XrInstance instance,
|
||||||
|
XrEventDataBuffer* eventData);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrResult value,
|
||||||
|
char buffer[XR_MAX_RESULT_STRING_SIZE]);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrStructureType value,
|
||||||
|
char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSystemGetInfo* getInfo,
|
||||||
|
XrSystemId* systemId);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrSystemProperties* properties);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t environmentBlendModeCapacityInput,
|
||||||
|
uint32_t* environmentBlendModeCountOutput,
|
||||||
|
XrEnvironmentBlendMode* environmentBlendModes);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrSessionCreateInfo* createInfo,
|
||||||
|
XrSession* session);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
|
||||||
|
XrSession session);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
|
||||||
|
XrSession session,
|
||||||
|
uint32_t spaceCapacityInput,
|
||||||
|
uint32_t* spaceCountOutput,
|
||||||
|
XrReferenceSpaceType* spaces);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
|
||||||
|
XrSession session,
|
||||||
|
const XrReferenceSpaceCreateInfo* createInfo,
|
||||||
|
XrSpace* space);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
|
||||||
|
XrSession session,
|
||||||
|
XrReferenceSpaceType referenceSpaceType,
|
||||||
|
XrExtent2Df* bounds);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionSpaceCreateInfo* createInfo,
|
||||||
|
XrSpace* space);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
|
||||||
|
XrSpace space,
|
||||||
|
XrSpace baseSpace,
|
||||||
|
XrTime time,
|
||||||
|
XrSpaceLocation* location);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
|
||||||
|
XrSpace space);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
uint32_t viewConfigurationTypeCapacityInput,
|
||||||
|
uint32_t* viewConfigurationTypeCountOutput,
|
||||||
|
XrViewConfigurationType* viewConfigurationTypes);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
XrViewConfigurationProperties* configurationProperties);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
|
||||||
|
XrInstance instance,
|
||||||
|
XrSystemId systemId,
|
||||||
|
XrViewConfigurationType viewConfigurationType,
|
||||||
|
uint32_t viewCapacityInput,
|
||||||
|
uint32_t* viewCountOutput,
|
||||||
|
XrViewConfigurationView* views);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
|
||||||
|
XrSession session,
|
||||||
|
uint32_t formatCapacityInput,
|
||||||
|
uint32_t* formatCountOutput,
|
||||||
|
int64_t* formats);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
|
||||||
|
XrSession session,
|
||||||
|
const XrSwapchainCreateInfo* createInfo,
|
||||||
|
XrSwapchain* swapchain);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
|
||||||
|
XrSwapchain swapchain);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
uint32_t imageCapacityInput,
|
||||||
|
uint32_t* imageCountOutput,
|
||||||
|
XrSwapchainImageBaseHeader* images);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageAcquireInfo* acquireInfo,
|
||||||
|
uint32_t* index);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageWaitInfo* waitInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
|
||||||
|
XrSwapchain swapchain,
|
||||||
|
const XrSwapchainImageReleaseInfo* releaseInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
|
||||||
|
XrSession session,
|
||||||
|
const XrSessionBeginInfo* beginInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
|
||||||
|
XrSession session);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
|
||||||
|
XrSession session);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameWaitInfo* frameWaitInfo,
|
||||||
|
XrFrameState* frameState);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameBeginInfo* frameBeginInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
|
||||||
|
XrSession session,
|
||||||
|
const XrFrameEndInfo* frameEndInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
|
||||||
|
XrSession session,
|
||||||
|
const XrViewLocateInfo* viewLocateInfo,
|
||||||
|
XrViewState* viewState,
|
||||||
|
uint32_t viewCapacityInput,
|
||||||
|
uint32_t* viewCountOutput,
|
||||||
|
XrView* views);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
|
||||||
|
XrInstance instance,
|
||||||
|
const char* pathString,
|
||||||
|
XrPath* path);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
|
||||||
|
XrInstance instance,
|
||||||
|
XrPath path,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrActionSetCreateInfo* createInfo,
|
||||||
|
XrActionSet* actionSet);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
|
||||||
|
XrActionSet actionSet);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
|
||||||
|
XrActionSet actionSet,
|
||||||
|
const XrActionCreateInfo* createInfo,
|
||||||
|
XrAction* action);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
|
||||||
|
XrAction action);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
|
||||||
|
XrInstance instance,
|
||||||
|
const XrInteractionProfileSuggestedBinding* suggestedBindings);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
|
||||||
|
XrSession session,
|
||||||
|
const XrSessionActionSetsAttachInfo* attachInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
|
||||||
|
XrSession session,
|
||||||
|
XrPath topLevelUserPath,
|
||||||
|
XrInteractionProfileState* interactionProfile);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateBoolean* state);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateFloat* state);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStateVector2f* state);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionStateGetInfo* getInfo,
|
||||||
|
XrActionStatePose* state);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
|
||||||
|
XrSession session,
|
||||||
|
const XrActionsSyncInfo* syncInfo);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
|
||||||
|
XrSession session,
|
||||||
|
const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
|
||||||
|
uint32_t sourceCapacityInput,
|
||||||
|
uint32_t* sourceCountOutput,
|
||||||
|
XrPath* sources);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
|
||||||
|
XrSession session,
|
||||||
|
const XrInputSourceLocalizedNameGetInfo* getInfo,
|
||||||
|
uint32_t bufferCapacityInput,
|
||||||
|
uint32_t* bufferCountOutput,
|
||||||
|
char* buffer);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
|
||||||
|
XrSession session,
|
||||||
|
const XrHapticActionInfo* hapticActionInfo,
|
||||||
|
const XrHapticBaseHeader* hapticFeedback);
|
||||||
|
extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
|
||||||
|
XrSession session,
|
||||||
|
const XrHapticActionInfo* hapticActionInfo);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
347
thirdparty/openxr/src/xr_generated_dispatch_table.c
vendored
Normal file
347
thirdparty/openxr/src/xr_generated_dispatch_table.c
vendored
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "xr_generated_dispatch_table.h"
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// Helper function to populate an instance dispatch table
|
||||||
|
void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
|
||||||
|
XrInstance instance,
|
||||||
|
PFN_xrGetInstanceProcAddr get_inst_proc_addr) {
|
||||||
|
|
||||||
|
// ---- Core 1.0 commands
|
||||||
|
table->GetInstanceProcAddr = get_inst_proc_addr;
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateInstance", (PFN_xrVoidFunction*)&table->CreateInstance));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyInstance", (PFN_xrVoidFunction*)&table->DestroyInstance));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction*)&table->GetInstanceProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrPollEvent", (PFN_xrVoidFunction*)&table->PollEvent));
|
||||||
|
(get_inst_proc_addr(instance, "xrResultToString", (PFN_xrVoidFunction*)&table->ResultToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrStructureTypeToString", (PFN_xrVoidFunction*)&table->StructureTypeToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSystem", (PFN_xrVoidFunction*)&table->GetSystem));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSystemProperties", (PFN_xrVoidFunction*)&table->GetSystemProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateEnvironmentBlendModes", (PFN_xrVoidFunction*)&table->EnumerateEnvironmentBlendModes));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSession", (PFN_xrVoidFunction*)&table->CreateSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySession", (PFN_xrVoidFunction*)&table->DestroySession));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateReferenceSpaces", (PFN_xrVoidFunction*)&table->EnumerateReferenceSpaces));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateReferenceSpace", (PFN_xrVoidFunction*)&table->CreateReferenceSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetReferenceSpaceBoundsRect", (PFN_xrVoidFunction*)&table->GetReferenceSpaceBoundsRect));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateActionSpace", (PFN_xrVoidFunction*)&table->CreateActionSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateSpace", (PFN_xrVoidFunction*)&table->LocateSpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySpace", (PFN_xrVoidFunction*)&table->DestroySpace));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurations));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetViewConfigurationProperties", (PFN_xrVoidFunction*)&table->GetViewConfigurationProperties));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateViewConfigurationViews", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurationViews));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateSwapchainFormats", (PFN_xrVoidFunction*)&table->EnumerateSwapchainFormats));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSwapchain", (PFN_xrVoidFunction*)&table->CreateSwapchain));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySwapchain", (PFN_xrVoidFunction*)&table->DestroySwapchain));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateSwapchainImages", (PFN_xrVoidFunction*)&table->EnumerateSwapchainImages));
|
||||||
|
(get_inst_proc_addr(instance, "xrAcquireSwapchainImage", (PFN_xrVoidFunction*)&table->AcquireSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrWaitSwapchainImage", (PFN_xrVoidFunction*)&table->WaitSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrReleaseSwapchainImage", (PFN_xrVoidFunction*)&table->ReleaseSwapchainImage));
|
||||||
|
(get_inst_proc_addr(instance, "xrBeginSession", (PFN_xrVoidFunction*)&table->BeginSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrEndSession", (PFN_xrVoidFunction*)&table->EndSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrRequestExitSession", (PFN_xrVoidFunction*)&table->RequestExitSession));
|
||||||
|
(get_inst_proc_addr(instance, "xrWaitFrame", (PFN_xrVoidFunction*)&table->WaitFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrBeginFrame", (PFN_xrVoidFunction*)&table->BeginFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrEndFrame", (PFN_xrVoidFunction*)&table->EndFrame));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateViews", (PFN_xrVoidFunction*)&table->LocateViews));
|
||||||
|
(get_inst_proc_addr(instance, "xrStringToPath", (PFN_xrVoidFunction*)&table->StringToPath));
|
||||||
|
(get_inst_proc_addr(instance, "xrPathToString", (PFN_xrVoidFunction*)&table->PathToString));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateActionSet", (PFN_xrVoidFunction*)&table->CreateActionSet));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyActionSet", (PFN_xrVoidFunction*)&table->DestroyActionSet));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateAction", (PFN_xrVoidFunction*)&table->CreateAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyAction", (PFN_xrVoidFunction*)&table->DestroyAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrSuggestInteractionProfileBindings", (PFN_xrVoidFunction*)&table->SuggestInteractionProfileBindings));
|
||||||
|
(get_inst_proc_addr(instance, "xrAttachSessionActionSets", (PFN_xrVoidFunction*)&table->AttachSessionActionSets));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetCurrentInteractionProfile", (PFN_xrVoidFunction*)&table->GetCurrentInteractionProfile));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateBoolean", (PFN_xrVoidFunction*)&table->GetActionStateBoolean));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateFloat", (PFN_xrVoidFunction*)&table->GetActionStateFloat));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStateVector2f", (PFN_xrVoidFunction*)&table->GetActionStateVector2f));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetActionStatePose", (PFN_xrVoidFunction*)&table->GetActionStatePose));
|
||||||
|
(get_inst_proc_addr(instance, "xrSyncActions", (PFN_xrVoidFunction*)&table->SyncActions));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateBoundSourcesForAction", (PFN_xrVoidFunction*)&table->EnumerateBoundSourcesForAction));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetInputSourceLocalizedName", (PFN_xrVoidFunction*)&table->GetInputSourceLocalizedName));
|
||||||
|
(get_inst_proc_addr(instance, "xrApplyHapticFeedback", (PFN_xrVoidFunction*)&table->ApplyHapticFeedback));
|
||||||
|
(get_inst_proc_addr(instance, "xrStopHapticFeedback", (PFN_xrVoidFunction*)&table->StopHapticFeedback));
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_thread_settings extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
(get_inst_proc_addr(instance, "xrSetAndroidApplicationThreadKHR", (PFN_xrVoidFunction*)&table->SetAndroidApplicationThreadKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_surface_swapchain extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSwapchainAndroidSurfaceKHR", (PFN_xrVoidFunction*)&table->CreateSwapchainAndroidSurfaceKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLESGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanInstanceExtensionsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanDeviceExtensionsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDeviceKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetD3D11GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D11GraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetD3D12GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D12GraphicsRequirementsKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
|
||||||
|
// ---- XR_KHR_visibility_mask extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVisibilityMaskKHR", (PFN_xrVoidFunction*)&table->GetVisibilityMaskKHR));
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertWin32PerformanceCounterToTimeKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToWin32PerformanceCounterKHR));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time extension commands
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimespecTimeToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimespecTimeToTimeKHR));
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
(get_inst_proc_addr(instance, "xrConvertTimeToTimespecTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToTimespecTimeKHR));
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable2 extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateVulkanInstanceKHR", (PFN_xrVoidFunction*)&table->CreateVulkanInstanceKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateVulkanDeviceKHR", (PFN_xrVoidFunction*)&table->CreateVulkanDeviceKHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsDevice2KHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDevice2KHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirements2KHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirements2KHR));
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_EXT_performance_settings extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrPerfSettingsSetPerformanceLevelEXT", (PFN_xrVoidFunction*)&table->PerfSettingsSetPerformanceLevelEXT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_thermal_query extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrThermalGetTemperatureTrendEXT", (PFN_xrVoidFunction*)&table->ThermalGetTemperatureTrendEXT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", (PFN_xrVoidFunction*)&table->SetDebugUtilsObjectNameEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->CreateDebugUtilsMessengerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->DestroyDebugUtilsMessengerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSubmitDebugUtilsMessageEXT", (PFN_xrVoidFunction*)&table->SubmitDebugUtilsMessageEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionBeginDebugUtilsLabelRegionEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionEndDebugUtilsLabelRegionEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSessionInsertDebugUtilsLabelEXT", (PFN_xrVoidFunction*)&table->SessionInsertDebugUtilsLabelEXT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_anchor extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialAnchorSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorSpaceMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->DestroySpatialAnchorMSFT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_conformance_automation extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetInputDeviceActiveEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceActiveEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetInputDeviceStateBoolEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateBoolEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetInputDeviceStateFloatEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateFloatEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetInputDeviceStateVector2fEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateVector2fEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetInputDeviceLocationEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceLocationEXT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_graph_bridge extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialGraphNodeSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialGraphNodeSpaceMSFT));
|
||||||
|
|
||||||
|
// ---- XR_EXT_hand_tracking extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateHandTrackerEXT", (PFN_xrVoidFunction*)&table->CreateHandTrackerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyHandTrackerEXT", (PFN_xrVoidFunction*)&table->DestroyHandTrackerEXT));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateHandJointsEXT", (PFN_xrVoidFunction*)&table->LocateHandJointsEXT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_hand_tracking_mesh extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateHandMeshSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateHandMeshSpaceMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrUpdateHandMeshMSFT", (PFN_xrVoidFunction*)&table->UpdateHandMeshMSFT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_controller_model extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrGetControllerModelKeyMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelKeyMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrLoadControllerModelMSFT", (PFN_xrVoidFunction*)&table->LoadControllerModelMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetControllerModelPropertiesMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelPropertiesMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetControllerModelStateMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelStateMSFT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_perception_anchor_interop extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialAnchorFromPerceptionAnchorMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorFromPerceptionAnchorMSFT));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrTryGetPerceptionAnchorFromSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->TryGetPerceptionAnchorFromSpatialAnchorMSFT));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_MSFT_composition_layer_reprojection extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateReprojectionModesMSFT", (PFN_xrVoidFunction*)&table->EnumerateReprojectionModesMSFT));
|
||||||
|
|
||||||
|
// ---- XR_FB_swapchain_update_state extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrUpdateSwapchainFB", (PFN_xrVoidFunction*)&table->UpdateSwapchainFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSwapchainStateFB", (PFN_xrVoidFunction*)&table->GetSwapchainStateFB));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_scene_understanding extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateSceneComputeFeaturesMSFT", (PFN_xrVoidFunction*)&table->EnumerateSceneComputeFeaturesMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSceneObserverMSFT", (PFN_xrVoidFunction*)&table->CreateSceneObserverMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySceneObserverMSFT", (PFN_xrVoidFunction*)&table->DestroySceneObserverMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSceneMSFT", (PFN_xrVoidFunction*)&table->CreateSceneMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySceneMSFT", (PFN_xrVoidFunction*)&table->DestroySceneMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrComputeNewSceneMSFT", (PFN_xrVoidFunction*)&table->ComputeNewSceneMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSceneComputeStateMSFT", (PFN_xrVoidFunction*)&table->GetSceneComputeStateMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSceneComponentsMSFT", (PFN_xrVoidFunction*)&table->GetSceneComponentsMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrLocateSceneComponentsMSFT", (PFN_xrVoidFunction*)&table->LocateSceneComponentsMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSceneMeshBuffersMSFT", (PFN_xrVoidFunction*)&table->GetSceneMeshBuffersMSFT));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_scene_understanding_serialization extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrDeserializeSceneMSFT", (PFN_xrVoidFunction*)&table->DeserializeSceneMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetSerializedSceneFragmentDataMSFT", (PFN_xrVoidFunction*)&table->GetSerializedSceneFragmentDataMSFT));
|
||||||
|
|
||||||
|
// ---- XR_FB_display_refresh_rate extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateDisplayRefreshRatesFB", (PFN_xrVoidFunction*)&table->EnumerateDisplayRefreshRatesFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetDisplayRefreshRateFB", (PFN_xrVoidFunction*)&table->GetDisplayRefreshRateFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrRequestDisplayRefreshRateFB", (PFN_xrVoidFunction*)&table->RequestDisplayRefreshRateFB));
|
||||||
|
|
||||||
|
// ---- XR_HTCX_vive_tracker_interaction extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateViveTrackerPathsHTCX", (PFN_xrVoidFunction*)&table->EnumerateViveTrackerPathsHTCX));
|
||||||
|
|
||||||
|
// ---- XR_HTC_facial_tracking extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateFacialTrackerHTC", (PFN_xrVoidFunction*)&table->CreateFacialTrackerHTC));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyFacialTrackerHTC", (PFN_xrVoidFunction*)&table->DestroyFacialTrackerHTC));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetFacialExpressionsHTC", (PFN_xrVoidFunction*)&table->GetFacialExpressionsHTC));
|
||||||
|
|
||||||
|
// ---- XR_FB_color_space extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateColorSpacesFB", (PFN_xrVoidFunction*)&table->EnumerateColorSpacesFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetColorSpaceFB", (PFN_xrVoidFunction*)&table->SetColorSpaceFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_hand_tracking_mesh extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrGetHandMeshFB", (PFN_xrVoidFunction*)&table->GetHandMeshFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_foveation extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateFoveationProfileFB", (PFN_xrVoidFunction*)&table->CreateFoveationProfileFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyFoveationProfileFB", (PFN_xrVoidFunction*)&table->DestroyFoveationProfileFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_keyboard_tracking extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrQuerySystemTrackedKeyboardFB", (PFN_xrVoidFunction*)&table->QuerySystemTrackedKeyboardFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateKeyboardSpaceFB", (PFN_xrVoidFunction*)&table->CreateKeyboardSpaceFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_triangle_mesh extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateTriangleMeshFB", (PFN_xrVoidFunction*)&table->CreateTriangleMeshFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyTriangleMeshFB", (PFN_xrVoidFunction*)&table->DestroyTriangleMeshFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshGetVertexBufferFB", (PFN_xrVoidFunction*)&table->TriangleMeshGetVertexBufferFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshGetIndexBufferFB", (PFN_xrVoidFunction*)&table->TriangleMeshGetIndexBufferFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshBeginUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshBeginUpdateFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshEndUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshEndUpdateFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshBeginVertexBufferUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshBeginVertexBufferUpdateFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrTriangleMeshEndVertexBufferUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshEndVertexBufferUpdateFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_passthrough extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreatePassthroughFB", (PFN_xrVoidFunction*)&table->CreatePassthroughFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyPassthroughFB", (PFN_xrVoidFunction*)&table->DestroyPassthroughFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughStartFB", (PFN_xrVoidFunction*)&table->PassthroughStartFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughPauseFB", (PFN_xrVoidFunction*)&table->PassthroughPauseFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreatePassthroughLayerFB", (PFN_xrVoidFunction*)&table->CreatePassthroughLayerFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyPassthroughLayerFB", (PFN_xrVoidFunction*)&table->DestroyPassthroughLayerFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughLayerPauseFB", (PFN_xrVoidFunction*)&table->PassthroughLayerPauseFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughLayerResumeFB", (PFN_xrVoidFunction*)&table->PassthroughLayerResumeFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughLayerSetStyleFB", (PFN_xrVoidFunction*)&table->PassthroughLayerSetStyleFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateGeometryInstanceFB", (PFN_xrVoidFunction*)&table->CreateGeometryInstanceFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroyGeometryInstanceFB", (PFN_xrVoidFunction*)&table->DestroyGeometryInstanceFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrGeometryInstanceSetTransformFB", (PFN_xrVoidFunction*)&table->GeometryInstanceSetTransformFB));
|
||||||
|
|
||||||
|
// ---- XR_FB_render_model extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumerateRenderModelPathsFB", (PFN_xrVoidFunction*)&table->EnumerateRenderModelPathsFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetRenderModelPropertiesFB", (PFN_xrVoidFunction*)&table->GetRenderModelPropertiesFB));
|
||||||
|
(get_inst_proc_addr(instance, "xrLoadRenderModelFB", (PFN_xrVoidFunction*)&table->LoadRenderModelFB));
|
||||||
|
|
||||||
|
// ---- XR_VARJO_environment_depth_estimation extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetEnvironmentDepthEstimationVARJO", (PFN_xrVoidFunction*)&table->SetEnvironmentDepthEstimationVARJO));
|
||||||
|
|
||||||
|
// ---- XR_VARJO_marker_tracking extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetMarkerTrackingVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingVARJO));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetMarkerTrackingTimeoutVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingTimeoutVARJO));
|
||||||
|
(get_inst_proc_addr(instance, "xrSetMarkerTrackingPredictionVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingPredictionVARJO));
|
||||||
|
(get_inst_proc_addr(instance, "xrGetMarkerSizeVARJO", (PFN_xrVoidFunction*)&table->GetMarkerSizeVARJO));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateMarkerSpaceVARJO", (PFN_xrVoidFunction*)&table->CreateMarkerSpaceVARJO));
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_anchor_persistence extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialAnchorStoreConnectionMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorStoreConnectionMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrDestroySpatialAnchorStoreConnectionMSFT", (PFN_xrVoidFunction*)&table->DestroySpatialAnchorStoreConnectionMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrPersistSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->PersistSpatialAnchorMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrEnumeratePersistedSpatialAnchorNamesMSFT", (PFN_xrVoidFunction*)&table->EnumeratePersistedSpatialAnchorNamesMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrCreateSpatialAnchorFromPersistedNameMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorFromPersistedNameMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrUnpersistSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->UnpersistSpatialAnchorMSFT));
|
||||||
|
(get_inst_proc_addr(instance, "xrClearSpatialAnchorStoreMSFT", (PFN_xrVoidFunction*)&table->ClearSpatialAnchorStoreMSFT));
|
||||||
|
|
||||||
|
// ---- XR_OCULUS_audio_device_guid extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetAudioOutputDeviceGuidOculus", (PFN_xrVoidFunction*)&table->GetAudioOutputDeviceGuidOculus));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
(get_inst_proc_addr(instance, "xrGetAudioInputDeviceGuidOculus", (PFN_xrVoidFunction*)&table->GetAudioInputDeviceGuidOculus));
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_ALMALENCE_digital_lens_control extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrSetDigitalLensControlALMALENCE", (PFN_xrVoidFunction*)&table->SetDigitalLensControlALMALENCE));
|
||||||
|
|
||||||
|
// ---- XR_FB_passthrough_keyboard_hands extension commands
|
||||||
|
(get_inst_proc_addr(instance, "xrPassthroughLayerSetKeyboardHandsIntensityFB", (PFN_xrVoidFunction*)&table->PassthroughLayerSetKeyboardHandsIntensityFB));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
355
thirdparty/openxr/src/xr_generated_dispatch_table.h
vendored
Normal file
355
thirdparty/openxr/src/xr_generated_dispatch_table.h
vendored
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
|
||||||
|
// See utility_source_generator.py for modifications
|
||||||
|
// ************************************************************
|
||||||
|
|
||||||
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
|
||||||
|
// Copyright (c) 2017-2019 Valve Corporation
|
||||||
|
// Copyright (c) 2017-2019 LunarG, Inc.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Author: Mark Young <marky@lunarg.com>
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "xr_dependencies.h"
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// Generated dispatch table
|
||||||
|
struct XrGeneratedDispatchTable {
|
||||||
|
|
||||||
|
// ---- Core 1.0 commands
|
||||||
|
PFN_xrGetInstanceProcAddr GetInstanceProcAddr;
|
||||||
|
PFN_xrEnumerateApiLayerProperties EnumerateApiLayerProperties;
|
||||||
|
PFN_xrEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||||
|
PFN_xrCreateInstance CreateInstance;
|
||||||
|
PFN_xrDestroyInstance DestroyInstance;
|
||||||
|
PFN_xrGetInstanceProperties GetInstanceProperties;
|
||||||
|
PFN_xrPollEvent PollEvent;
|
||||||
|
PFN_xrResultToString ResultToString;
|
||||||
|
PFN_xrStructureTypeToString StructureTypeToString;
|
||||||
|
PFN_xrGetSystem GetSystem;
|
||||||
|
PFN_xrGetSystemProperties GetSystemProperties;
|
||||||
|
PFN_xrEnumerateEnvironmentBlendModes EnumerateEnvironmentBlendModes;
|
||||||
|
PFN_xrCreateSession CreateSession;
|
||||||
|
PFN_xrDestroySession DestroySession;
|
||||||
|
PFN_xrEnumerateReferenceSpaces EnumerateReferenceSpaces;
|
||||||
|
PFN_xrCreateReferenceSpace CreateReferenceSpace;
|
||||||
|
PFN_xrGetReferenceSpaceBoundsRect GetReferenceSpaceBoundsRect;
|
||||||
|
PFN_xrCreateActionSpace CreateActionSpace;
|
||||||
|
PFN_xrLocateSpace LocateSpace;
|
||||||
|
PFN_xrDestroySpace DestroySpace;
|
||||||
|
PFN_xrEnumerateViewConfigurations EnumerateViewConfigurations;
|
||||||
|
PFN_xrGetViewConfigurationProperties GetViewConfigurationProperties;
|
||||||
|
PFN_xrEnumerateViewConfigurationViews EnumerateViewConfigurationViews;
|
||||||
|
PFN_xrEnumerateSwapchainFormats EnumerateSwapchainFormats;
|
||||||
|
PFN_xrCreateSwapchain CreateSwapchain;
|
||||||
|
PFN_xrDestroySwapchain DestroySwapchain;
|
||||||
|
PFN_xrEnumerateSwapchainImages EnumerateSwapchainImages;
|
||||||
|
PFN_xrAcquireSwapchainImage AcquireSwapchainImage;
|
||||||
|
PFN_xrWaitSwapchainImage WaitSwapchainImage;
|
||||||
|
PFN_xrReleaseSwapchainImage ReleaseSwapchainImage;
|
||||||
|
PFN_xrBeginSession BeginSession;
|
||||||
|
PFN_xrEndSession EndSession;
|
||||||
|
PFN_xrRequestExitSession RequestExitSession;
|
||||||
|
PFN_xrWaitFrame WaitFrame;
|
||||||
|
PFN_xrBeginFrame BeginFrame;
|
||||||
|
PFN_xrEndFrame EndFrame;
|
||||||
|
PFN_xrLocateViews LocateViews;
|
||||||
|
PFN_xrStringToPath StringToPath;
|
||||||
|
PFN_xrPathToString PathToString;
|
||||||
|
PFN_xrCreateActionSet CreateActionSet;
|
||||||
|
PFN_xrDestroyActionSet DestroyActionSet;
|
||||||
|
PFN_xrCreateAction CreateAction;
|
||||||
|
PFN_xrDestroyAction DestroyAction;
|
||||||
|
PFN_xrSuggestInteractionProfileBindings SuggestInteractionProfileBindings;
|
||||||
|
PFN_xrAttachSessionActionSets AttachSessionActionSets;
|
||||||
|
PFN_xrGetCurrentInteractionProfile GetCurrentInteractionProfile;
|
||||||
|
PFN_xrGetActionStateBoolean GetActionStateBoolean;
|
||||||
|
PFN_xrGetActionStateFloat GetActionStateFloat;
|
||||||
|
PFN_xrGetActionStateVector2f GetActionStateVector2f;
|
||||||
|
PFN_xrGetActionStatePose GetActionStatePose;
|
||||||
|
PFN_xrSyncActions SyncActions;
|
||||||
|
PFN_xrEnumerateBoundSourcesForAction EnumerateBoundSourcesForAction;
|
||||||
|
PFN_xrGetInputSourceLocalizedName GetInputSourceLocalizedName;
|
||||||
|
PFN_xrApplyHapticFeedback ApplyHapticFeedback;
|
||||||
|
PFN_xrStopHapticFeedback StopHapticFeedback;
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_thread_settings extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
PFN_xrSetAndroidApplicationThreadKHR SetAndroidApplicationThreadKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_android_surface_swapchain extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
PFN_xrCreateSwapchainAndroidSurfaceKHR CreateSwapchainAndroidSurfaceKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_ANDROID)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
PFN_xrGetOpenGLGraphicsRequirementsKHR GetOpenGLGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
|
||||||
|
|
||||||
|
// ---- XR_KHR_opengl_es_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
PFN_xrGetOpenGLESGraphicsRequirementsKHR GetOpenGLESGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanInstanceExtensionsKHR GetVulkanInstanceExtensionsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanDeviceExtensionsKHR GetVulkanDeviceExtensionsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsDeviceKHR GetVulkanGraphicsDeviceKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsRequirementsKHR GetVulkanGraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D11_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
PFN_xrGetD3D11GraphicsRequirementsKHR GetD3D11GraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D11)
|
||||||
|
|
||||||
|
// ---- XR_KHR_D3D12_enable extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
PFN_xrGetD3D12GraphicsRequirementsKHR GetD3D12GraphicsRequirementsKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_D3D12)
|
||||||
|
|
||||||
|
// ---- XR_KHR_visibility_mask extension commands
|
||||||
|
PFN_xrGetVisibilityMaskKHR GetVisibilityMaskKHR;
|
||||||
|
|
||||||
|
// ---- XR_KHR_win32_convert_performance_counter_time extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrConvertWin32PerformanceCounterToTimeKHR ConvertWin32PerformanceCounterToTimeKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrConvertTimeToWin32PerformanceCounterKHR ConvertTimeToWin32PerformanceCounterKHR;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_KHR_convert_timespec_time extension commands
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
PFN_xrConvertTimespecTimeToTimeKHR ConvertTimespecTimeToTimeKHR;
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
#if defined(XR_USE_TIMESPEC)
|
||||||
|
PFN_xrConvertTimeToTimespecTimeKHR ConvertTimeToTimespecTimeKHR;
|
||||||
|
#endif // defined(XR_USE_TIMESPEC)
|
||||||
|
|
||||||
|
// ---- XR_KHR_loader_init extension commands
|
||||||
|
PFN_xrInitializeLoaderKHR InitializeLoaderKHR;
|
||||||
|
|
||||||
|
// ---- XR_KHR_vulkan_enable2 extension commands
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrCreateVulkanInstanceKHR CreateVulkanInstanceKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrCreateVulkanDeviceKHR CreateVulkanDeviceKHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsDevice2KHR GetVulkanGraphicsDevice2KHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
#if defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
PFN_xrGetVulkanGraphicsRequirements2KHR GetVulkanGraphicsRequirements2KHR;
|
||||||
|
#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
|
||||||
|
|
||||||
|
// ---- XR_EXT_performance_settings extension commands
|
||||||
|
PFN_xrPerfSettingsSetPerformanceLevelEXT PerfSettingsSetPerformanceLevelEXT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_thermal_query extension commands
|
||||||
|
PFN_xrThermalGetTemperatureTrendEXT ThermalGetTemperatureTrendEXT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_debug_utils extension commands
|
||||||
|
PFN_xrSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
|
||||||
|
PFN_xrCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
|
||||||
|
PFN_xrDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
|
||||||
|
PFN_xrSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
|
||||||
|
PFN_xrSessionBeginDebugUtilsLabelRegionEXT SessionBeginDebugUtilsLabelRegionEXT;
|
||||||
|
PFN_xrSessionEndDebugUtilsLabelRegionEXT SessionEndDebugUtilsLabelRegionEXT;
|
||||||
|
PFN_xrSessionInsertDebugUtilsLabelEXT SessionInsertDebugUtilsLabelEXT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_anchor extension commands
|
||||||
|
PFN_xrCreateSpatialAnchorMSFT CreateSpatialAnchorMSFT;
|
||||||
|
PFN_xrCreateSpatialAnchorSpaceMSFT CreateSpatialAnchorSpaceMSFT;
|
||||||
|
PFN_xrDestroySpatialAnchorMSFT DestroySpatialAnchorMSFT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_conformance_automation extension commands
|
||||||
|
PFN_xrSetInputDeviceActiveEXT SetInputDeviceActiveEXT;
|
||||||
|
PFN_xrSetInputDeviceStateBoolEXT SetInputDeviceStateBoolEXT;
|
||||||
|
PFN_xrSetInputDeviceStateFloatEXT SetInputDeviceStateFloatEXT;
|
||||||
|
PFN_xrSetInputDeviceStateVector2fEXT SetInputDeviceStateVector2fEXT;
|
||||||
|
PFN_xrSetInputDeviceLocationEXT SetInputDeviceLocationEXT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_graph_bridge extension commands
|
||||||
|
PFN_xrCreateSpatialGraphNodeSpaceMSFT CreateSpatialGraphNodeSpaceMSFT;
|
||||||
|
|
||||||
|
// ---- XR_EXT_hand_tracking extension commands
|
||||||
|
PFN_xrCreateHandTrackerEXT CreateHandTrackerEXT;
|
||||||
|
PFN_xrDestroyHandTrackerEXT DestroyHandTrackerEXT;
|
||||||
|
PFN_xrLocateHandJointsEXT LocateHandJointsEXT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_hand_tracking_mesh extension commands
|
||||||
|
PFN_xrCreateHandMeshSpaceMSFT CreateHandMeshSpaceMSFT;
|
||||||
|
PFN_xrUpdateHandMeshMSFT UpdateHandMeshMSFT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_controller_model extension commands
|
||||||
|
PFN_xrGetControllerModelKeyMSFT GetControllerModelKeyMSFT;
|
||||||
|
PFN_xrLoadControllerModelMSFT LoadControllerModelMSFT;
|
||||||
|
PFN_xrGetControllerModelPropertiesMSFT GetControllerModelPropertiesMSFT;
|
||||||
|
PFN_xrGetControllerModelStateMSFT GetControllerModelStateMSFT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_perception_anchor_interop extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT CreateSpatialAnchorFromPerceptionAnchorMSFT;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT TryGetPerceptionAnchorFromSpatialAnchorMSFT;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_MSFT_composition_layer_reprojection extension commands
|
||||||
|
PFN_xrEnumerateReprojectionModesMSFT EnumerateReprojectionModesMSFT;
|
||||||
|
|
||||||
|
// ---- XR_FB_swapchain_update_state extension commands
|
||||||
|
PFN_xrUpdateSwapchainFB UpdateSwapchainFB;
|
||||||
|
PFN_xrGetSwapchainStateFB GetSwapchainStateFB;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_scene_understanding extension commands
|
||||||
|
PFN_xrEnumerateSceneComputeFeaturesMSFT EnumerateSceneComputeFeaturesMSFT;
|
||||||
|
PFN_xrCreateSceneObserverMSFT CreateSceneObserverMSFT;
|
||||||
|
PFN_xrDestroySceneObserverMSFT DestroySceneObserverMSFT;
|
||||||
|
PFN_xrCreateSceneMSFT CreateSceneMSFT;
|
||||||
|
PFN_xrDestroySceneMSFT DestroySceneMSFT;
|
||||||
|
PFN_xrComputeNewSceneMSFT ComputeNewSceneMSFT;
|
||||||
|
PFN_xrGetSceneComputeStateMSFT GetSceneComputeStateMSFT;
|
||||||
|
PFN_xrGetSceneComponentsMSFT GetSceneComponentsMSFT;
|
||||||
|
PFN_xrLocateSceneComponentsMSFT LocateSceneComponentsMSFT;
|
||||||
|
PFN_xrGetSceneMeshBuffersMSFT GetSceneMeshBuffersMSFT;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_scene_understanding_serialization extension commands
|
||||||
|
PFN_xrDeserializeSceneMSFT DeserializeSceneMSFT;
|
||||||
|
PFN_xrGetSerializedSceneFragmentDataMSFT GetSerializedSceneFragmentDataMSFT;
|
||||||
|
|
||||||
|
// ---- XR_FB_display_refresh_rate extension commands
|
||||||
|
PFN_xrEnumerateDisplayRefreshRatesFB EnumerateDisplayRefreshRatesFB;
|
||||||
|
PFN_xrGetDisplayRefreshRateFB GetDisplayRefreshRateFB;
|
||||||
|
PFN_xrRequestDisplayRefreshRateFB RequestDisplayRefreshRateFB;
|
||||||
|
|
||||||
|
// ---- XR_HTCX_vive_tracker_interaction extension commands
|
||||||
|
PFN_xrEnumerateViveTrackerPathsHTCX EnumerateViveTrackerPathsHTCX;
|
||||||
|
|
||||||
|
// ---- XR_HTC_facial_tracking extension commands
|
||||||
|
PFN_xrCreateFacialTrackerHTC CreateFacialTrackerHTC;
|
||||||
|
PFN_xrDestroyFacialTrackerHTC DestroyFacialTrackerHTC;
|
||||||
|
PFN_xrGetFacialExpressionsHTC GetFacialExpressionsHTC;
|
||||||
|
|
||||||
|
// ---- XR_FB_color_space extension commands
|
||||||
|
PFN_xrEnumerateColorSpacesFB EnumerateColorSpacesFB;
|
||||||
|
PFN_xrSetColorSpaceFB SetColorSpaceFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_hand_tracking_mesh extension commands
|
||||||
|
PFN_xrGetHandMeshFB GetHandMeshFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_foveation extension commands
|
||||||
|
PFN_xrCreateFoveationProfileFB CreateFoveationProfileFB;
|
||||||
|
PFN_xrDestroyFoveationProfileFB DestroyFoveationProfileFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_keyboard_tracking extension commands
|
||||||
|
PFN_xrQuerySystemTrackedKeyboardFB QuerySystemTrackedKeyboardFB;
|
||||||
|
PFN_xrCreateKeyboardSpaceFB CreateKeyboardSpaceFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_triangle_mesh extension commands
|
||||||
|
PFN_xrCreateTriangleMeshFB CreateTriangleMeshFB;
|
||||||
|
PFN_xrDestroyTriangleMeshFB DestroyTriangleMeshFB;
|
||||||
|
PFN_xrTriangleMeshGetVertexBufferFB TriangleMeshGetVertexBufferFB;
|
||||||
|
PFN_xrTriangleMeshGetIndexBufferFB TriangleMeshGetIndexBufferFB;
|
||||||
|
PFN_xrTriangleMeshBeginUpdateFB TriangleMeshBeginUpdateFB;
|
||||||
|
PFN_xrTriangleMeshEndUpdateFB TriangleMeshEndUpdateFB;
|
||||||
|
PFN_xrTriangleMeshBeginVertexBufferUpdateFB TriangleMeshBeginVertexBufferUpdateFB;
|
||||||
|
PFN_xrTriangleMeshEndVertexBufferUpdateFB TriangleMeshEndVertexBufferUpdateFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_passthrough extension commands
|
||||||
|
PFN_xrCreatePassthroughFB CreatePassthroughFB;
|
||||||
|
PFN_xrDestroyPassthroughFB DestroyPassthroughFB;
|
||||||
|
PFN_xrPassthroughStartFB PassthroughStartFB;
|
||||||
|
PFN_xrPassthroughPauseFB PassthroughPauseFB;
|
||||||
|
PFN_xrCreatePassthroughLayerFB CreatePassthroughLayerFB;
|
||||||
|
PFN_xrDestroyPassthroughLayerFB DestroyPassthroughLayerFB;
|
||||||
|
PFN_xrPassthroughLayerPauseFB PassthroughLayerPauseFB;
|
||||||
|
PFN_xrPassthroughLayerResumeFB PassthroughLayerResumeFB;
|
||||||
|
PFN_xrPassthroughLayerSetStyleFB PassthroughLayerSetStyleFB;
|
||||||
|
PFN_xrCreateGeometryInstanceFB CreateGeometryInstanceFB;
|
||||||
|
PFN_xrDestroyGeometryInstanceFB DestroyGeometryInstanceFB;
|
||||||
|
PFN_xrGeometryInstanceSetTransformFB GeometryInstanceSetTransformFB;
|
||||||
|
|
||||||
|
// ---- XR_FB_render_model extension commands
|
||||||
|
PFN_xrEnumerateRenderModelPathsFB EnumerateRenderModelPathsFB;
|
||||||
|
PFN_xrGetRenderModelPropertiesFB GetRenderModelPropertiesFB;
|
||||||
|
PFN_xrLoadRenderModelFB LoadRenderModelFB;
|
||||||
|
|
||||||
|
// ---- XR_VARJO_environment_depth_estimation extension commands
|
||||||
|
PFN_xrSetEnvironmentDepthEstimationVARJO SetEnvironmentDepthEstimationVARJO;
|
||||||
|
|
||||||
|
// ---- XR_VARJO_marker_tracking extension commands
|
||||||
|
PFN_xrSetMarkerTrackingVARJO SetMarkerTrackingVARJO;
|
||||||
|
PFN_xrSetMarkerTrackingTimeoutVARJO SetMarkerTrackingTimeoutVARJO;
|
||||||
|
PFN_xrSetMarkerTrackingPredictionVARJO SetMarkerTrackingPredictionVARJO;
|
||||||
|
PFN_xrGetMarkerSizeVARJO GetMarkerSizeVARJO;
|
||||||
|
PFN_xrCreateMarkerSpaceVARJO CreateMarkerSpaceVARJO;
|
||||||
|
|
||||||
|
// ---- XR_MSFT_spatial_anchor_persistence extension commands
|
||||||
|
PFN_xrCreateSpatialAnchorStoreConnectionMSFT CreateSpatialAnchorStoreConnectionMSFT;
|
||||||
|
PFN_xrDestroySpatialAnchorStoreConnectionMSFT DestroySpatialAnchorStoreConnectionMSFT;
|
||||||
|
PFN_xrPersistSpatialAnchorMSFT PersistSpatialAnchorMSFT;
|
||||||
|
PFN_xrEnumeratePersistedSpatialAnchorNamesMSFT EnumeratePersistedSpatialAnchorNamesMSFT;
|
||||||
|
PFN_xrCreateSpatialAnchorFromPersistedNameMSFT CreateSpatialAnchorFromPersistedNameMSFT;
|
||||||
|
PFN_xrUnpersistSpatialAnchorMSFT UnpersistSpatialAnchorMSFT;
|
||||||
|
PFN_xrClearSpatialAnchorStoreMSFT ClearSpatialAnchorStoreMSFT;
|
||||||
|
|
||||||
|
// ---- XR_OCULUS_audio_device_guid extension commands
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrGetAudioOutputDeviceGuidOculus GetAudioOutputDeviceGuidOculus;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
#if defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
PFN_xrGetAudioInputDeviceGuidOculus GetAudioInputDeviceGuidOculus;
|
||||||
|
#endif // defined(XR_USE_PLATFORM_WIN32)
|
||||||
|
|
||||||
|
// ---- XR_ALMALENCE_digital_lens_control extension commands
|
||||||
|
PFN_xrSetDigitalLensControlALMALENCE SetDigitalLensControlALMALENCE;
|
||||||
|
|
||||||
|
// ---- XR_FB_passthrough_keyboard_hands extension commands
|
||||||
|
PFN_xrPassthroughLayerSetKeyboardHandsIntensityFB PassthroughLayerSetKeyboardHandsIntensityFB;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Prototype for dispatch table helper function
|
||||||
|
void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
|
||||||
|
XrInstance instance,
|
||||||
|
PFN_xrGetInstanceProcAddr get_inst_proc_addr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
Reference in New Issue
Block a user