Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/openxr/src/loader/loader_init_data.cpp
20953 views
1
// Copyright (c) 2017-2025 The Khronos Group Inc.
2
// Copyright (c) 2017-2019 Valve Corporation
3
// Copyright (c) 2017-2019 LunarG, Inc.
4
//
5
// SPDX-License-Identifier: Apache-2.0 OR MIT
6
//
7
// Initial Author: Mark Young <[email protected]>
8
//
9
10
#include "loader_logger.hpp"
11
#include "runtime_interface.hpp"
12
#include "loader_instance.hpp"
13
#include "loader_init_data.hpp"
14
#include "loader_properties.hpp"
15
16
XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) {
17
// We iterate the chain per struct type, so we only pick the first of each type in the chain.
18
19
XrResult result = initializeProperties(info);
20
if (result != XR_SUCCESS) {
21
return result;
22
}
23
24
#if defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
25
result = initializePlatform(info);
26
if (result != XR_SUCCESS) {
27
return result;
28
}
29
#endif // defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
30
31
_initialized = true;
32
return XR_SUCCESS;
33
}
34
35
XrResult LoaderInitData::initializeProperties(const XrLoaderInitInfoBaseHeaderKHR* info) {
36
while (info != nullptr) {
37
if (info->type == XR_TYPE_LOADER_INIT_INFO_PROPERTIES_EXT) {
38
const auto* propertyInfo = reinterpret_cast<XrLoaderInitInfoPropertiesEXT const*>(info);
39
40
// Validate the inputs first.
41
for (uint32_t i = 0; i < propertyInfo->propertyValueCount; i++) {
42
if (propertyInfo->propertyValues[i].name == nullptr) {
43
return XR_ERROR_VALIDATION_FAILURE;
44
}
45
if (propertyInfo->propertyValues[i].value == nullptr) {
46
return XR_ERROR_VALIDATION_FAILURE;
47
}
48
std::string view{propertyInfo->propertyValues[i].name};
49
if (view.size() == 0) {
50
return XR_ERROR_VALIDATION_FAILURE;
51
}
52
}
53
54
// Inject provided properties into the loader property store.
55
LoaderProperty::ClearOverrides();
56
for (uint32_t i = 0; i < propertyInfo->propertyValueCount; i++) {
57
LoaderProperty::SetOverride(propertyInfo->propertyValues[i].name, propertyInfo->propertyValues[i].value);
58
}
59
// Take only the first such struct.
60
return XR_SUCCESS;
61
}
62
info = reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(info->next);
63
}
64
65
// fine if we don't find this.
66
return XR_SUCCESS;
67
}
68
69
#if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
70
XrResult LoaderInitData::initializePlatform(const XrLoaderInitInfoBaseHeaderKHR* info) {
71
// Check and copy the Android-specific init data.
72
while (info != nullptr) {
73
if (info->type == XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) {
74
auto cast_info = reinterpret_cast<XrLoaderInitInfoAndroidKHR const*>(info);
75
76
if (cast_info->applicationVM == nullptr) {
77
return XR_ERROR_VALIDATION_FAILURE;
78
}
79
if (cast_info->applicationContext == nullptr) {
80
return XR_ERROR_VALIDATION_FAILURE;
81
}
82
83
// Copy and store the JVM pointer and Android Context, ensuring the JVM is initialised.
84
_platform_info = *cast_info;
85
_platform_info.next = nullptr; // Not safe to store next pointer since the memory may not exist later.
86
87
if (_platform_info.applicationVM == nullptr) {
88
return XR_ERROR_VALIDATION_FAILURE;
89
}
90
if (_platform_info.applicationContext == nullptr) {
91
return XR_ERROR_VALIDATION_FAILURE;
92
}
93
jni::init(static_cast<jni::JavaVM*>(_platform_info.applicationVM));
94
const jni::Object context = jni::Object{static_cast<jni::jobject>(_platform_info.applicationContext)};
95
96
// Retrieve a reference to the Android AssetManager.
97
const auto assetManager = context.call<jni::Object>("getAssets()Landroid/content/res/AssetManager;");
98
_android_asset_manager = AAssetManager_fromJava(jni::env(), assetManager.getHandle());
99
100
// Retrieve the path to the native libraries.
101
const auto applicationContext = context.call<jni::Object>("getApplicationContext()Landroid/content/Context;");
102
const auto applicationInfo = context.call<jni::Object>("getApplicationInfo()Landroid/content/pm/ApplicationInfo;");
103
_android_native_library_path = applicationInfo.get<std::string>("nativeLibraryDir");
104
105
// Take only the first such struct.
106
return XR_SUCCESS;
107
}
108
info = reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(info->next);
109
}
110
111
// We didn't find one.
112
return XR_ERROR_VALIDATION_FAILURE;
113
}
114
#endif // defined(XR_USE_PLATFORM_ANDROID) && defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
115
116
XrResult InitializeLoaderInitData(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) {
117
if (!ActiveLoaderInstance::IsAvailable()) {
118
LoaderLogger::LogVerboseMessage("InitializeLoaderInitData", "Unloading any previously loaded runtime");
119
// This will not shutdown the runtime, only unload the library.
120
RuntimeInterface::UnloadRuntime("InitializeLoaderInitData");
121
} else {
122
LoaderLogger::LogErrorMessage("InitializeLoaderInitData",
123
"An active instance currently exists while trying to reinitialize the loader");
124
return XR_ERROR_INITIALIZATION_FAILED;
125
}
126
return LoaderInitData::instance().initialize(loaderInitInfo);
127
}
128
129
#if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
130
std::string GetAndroidNativeLibraryDir() { return LoaderInitData::instance()._android_native_library_path; }
131
132
void* GetAndroidAssetManager() { return LoaderInitData::instance()._android_asset_manager; }
133
#endif // defined(XR_USE_PLATFORM_ANDROID) && defined(XR_HAS_REQUIRED_PLATFORM_LOADER_INIT_STRUCT)
134
135