diff options
Diffstat (limited to 'thirdparty/openxr/src')
-rw-r--r-- | thirdparty/openxr/src/common/unique_asset.h | 33 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/android_utilities.cpp | 2 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/api_layer_interface.cpp | 1 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/loader_core.cpp | 6 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/manifest_file.cpp | 120 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/manifest_file.hpp | 14 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/runtime_interface.cpp | 37 | ||||
-rw-r--r-- | thirdparty/openxr/src/loader/runtime_interface.hpp | 2 |
8 files changed, 199 insertions, 16 deletions
diff --git a/thirdparty/openxr/src/common/unique_asset.h b/thirdparty/openxr/src/common/unique_asset.h new file mode 100644 index 0000000000..4929039a03 --- /dev/null +++ b/thirdparty/openxr/src/common/unique_asset.h @@ -0,0 +1,33 @@ +// Copyright (c) 2017-2022, The Khronos Group Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +#pragma once + +#ifdef XR_USE_PLATFORM_ANDROID + +#include <memory> +#include <android/asset_manager.h> + +namespace deleters { +struct AAssetDeleter { + void operator()(AAsset* asset) const noexcept { + if (asset != nullptr) { + AAsset_close(asset); + } + } +}; + +struct AAssetDirDeleter { + void operator()(AAssetDir* dir) const noexcept { + if (dir != nullptr) { + AAssetDir_close(dir); + } + } +}; + +} // namespace deleters + +using UniqueAsset = std::unique_ptr<AAsset, deleters::AAssetDeleter>; +using UniqueAssetDir = std::unique_ptr<AAssetDir, deleters::AAssetDirDeleter>; + +#endif diff --git a/thirdparty/openxr/src/loader/android_utilities.cpp b/thirdparty/openxr/src/loader/android_utilities.cpp index 807a775820..59d9a99b74 100644 --- a/thirdparty/openxr/src/loader/android_utilities.cpp +++ b/thirdparty/openxr/src/loader/android_utilities.cpp @@ -299,7 +299,7 @@ int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &conte 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")); + packageName.c_str(), filename.c_str(), libDir.c_str(), (hasFunctions ? "yes" : "no")); auto lib_path = libDir + "/" + filename; cursor.close(); diff --git a/thirdparty/openxr/src/loader/api_layer_interface.cpp b/thirdparty/openxr/src/loader/api_layer_interface.cpp index c3fd5bb7f1..b946e09402 100644 --- a/thirdparty/openxr/src/loader/api_layer_interface.cpp +++ b/thirdparty/openxr/src/loader/api_layer_interface.cpp @@ -53,7 +53,6 @@ XrResult ApiLayerInterface::GetApiLayerProperties(const std::string& openxr_comm 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++) { diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp index 375f1c93ba..a8bbfb4de2 100644 --- a/thirdparty/openxr/src/loader/loader_core.cpp +++ b/thirdparty/openxr/src/loader/loader_core.cpp @@ -711,9 +711,6 @@ 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"); @@ -726,6 +723,9 @@ XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, return XR_ERROR_VALIDATION_FAILURE; } + // Initialize the function to nullptr in case it does not get caught in a known case + *function = nullptr; + LoaderInstance *loader_instance = nullptr; if (instance == XR_NULL_HANDLE) { // Null instance is allowed for a few specific API entry points, otherwise return error diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp index e4eab3949e..df99d51f8f 100644 --- a/thirdparty/openxr/src/loader/manifest_file.cpp +++ b/thirdparty/openxr/src/loader/manifest_file.cpp @@ -21,6 +21,7 @@ #include "loader_platform.hpp" #include "platform_utils.hpp" #include "loader_logger.hpp" +#include "unique_asset.h" #include <json/json.h> #include <openxr/openxr.h> @@ -50,6 +51,10 @@ #define SYSCONFDIR "/etc" #endif // !SYSCONFDIR +#ifdef XR_USE_PLATFORM_ANDROID +#include <android/asset_manager.h> +#endif + #ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING #if JSON_USE_EXCEPTIONS #error \ @@ -656,17 +661,68 @@ ApiLayerManifestFile::ApiLayerManifestFile(ManifestFileType type, const std::str _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); +#ifdef XR_USE_PLATFORM_ANDROID +void ApiLayerManifestFile::AddManifestFilesAndroid(ManifestFileType type, + std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) { + AAssetManager *assetManager = (AAssetManager *)Android_Get_Asset_Manager(); + std::vector<std::string> filenames; + { + std::string search_path = ""; + switch (type) { + case MANIFEST_TYPE_IMPLICIT_API_LAYER: + search_path = "openxr/1/api_layers/implicit.d/"; + break; + case MANIFEST_TYPE_EXPLICIT_API_LAYER: + search_path = "openxr/1/api_layers/explicit.d/"; + break; + default: + return; + } - 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; + UniqueAssetDir dir{AAssetManager_openDir(assetManager, search_path.c_str())}; + if (!dir) { + return; + } + const std::string json = ".json"; + const char *fn = nullptr; + while ((fn = AAssetDir_getNextFileName(dir.get())) != nullptr) { + const std::string filename = search_path + fn; + if (filename.size() < json.size()) { + continue; + } + if (filename.compare(filename.size() - json.size(), json.size(), json) == 0) { + filenames.push_back(filename); + } + } } + for (const auto &filename : filenames) { + UniqueAsset asset{AAssetManager_open(assetManager, filename.c_str(), AASSET_MODE_BUFFER)}; + if (!asset) { + LoaderLogger::LogWarningMessage( + "", "ApiLayerManifestFile::AddManifestFilesAndroid unable to open asset " + filename + ", skipping"); + + continue; + } + size_t length = AAsset_getLength(asset.get()); + const char *buf = reinterpret_cast<const char *>(AAsset_getBuffer(asset.get())); + if (!buf) { + LoaderLogger::LogWarningMessage( + "", "ApiLayerManifestFile::AddManifestFilesAndroid unable to access asset" + filename + ", skipping"); + continue; + } + std::istringstream json_stream(std::string{buf, length}); + + CreateIfValid(ManifestFileType::MANIFEST_TYPE_EXPLICIT_API_LAYER, filename, json_stream, + &ApiLayerManifestFile::LocateLibraryInAssets, manifest_files); + } +} +#endif // XR_USE_PLATFORM_ANDROID + +void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::string &filename, std::istream &json_stream, + LibraryLocator locate_library, + std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) { + std::ostringstream error_ss("ApiLayerManifestFile::CreateIfValid "); Json::CharReaderBuilder builder; std::string errors; Json::Value root_node = Json::nullValue; @@ -757,9 +813,7 @@ void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::strin } 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)) { + if (!locate_library(filename, library_path, combined_path)) { error_ss << filename << " library " << combined_path << " does not appear to exist"; LoaderLogger::LogErrorMessage("", error_ss.str()); return; @@ -781,6 +835,46 @@ void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::strin manifest_files.back()->ParseCommon(layer_root_node); } +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); + if (!json_stream.is_open()) { + std::ostringstream error_ss("ApiLayerManifestFile::CreateIfValid "); + error_ss << "failed to open " << filename << ". Does it exist?"; + LoaderLogger::LogErrorMessage("", error_ss.str()); + return; + } + CreateIfValid(type, filename, json_stream, &ApiLayerManifestFile::LocateLibraryRelativeToJson, manifest_files); +} + +bool ApiLayerManifestFile::LocateLibraryRelativeToJson( + const std::string &json_filename, const std::string &library_path, + std::string &out_combined_path) { // Otherwise, treat the library path as a relative path based on the JSON file. + std::string combined_path; + std::string file_parent; + if (!FileSysUtilsGetParentPath(json_filename, file_parent) || + !FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) { + out_combined_path = combined_path; + return false; + } + out_combined_path = combined_path; + return true; +} + +#ifdef XR_USE_PLATFORM_ANDROID +bool ApiLayerManifestFile::LocateLibraryInAssets(const std::string & /* json_filename */, const std::string &library_path, + std::string &out_combined_path) { + std::string combined_path; + std::string file_parent = GetAndroidNativeLibraryDir(); + if (!FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) { + out_combined_path = combined_path; + return false; + } + out_combined_path = combined_path; + return true; +} +#endif + void ApiLayerManifestFile::PopulateApiLayerProperties(XrApiLayerProperties &props) const { props.layerVersion = _implementation_version; props.specVersion = XR_MAKE_VERSION(_api_version.major, _api_version.minor, _api_version.patch); @@ -841,5 +935,9 @@ XrResult ApiLayerManifestFile::FindManifestFiles(ManifestFileType type, ApiLayerManifestFile::CreateIfValid(type, cur_file, manifest_files); } +#ifdef XR_USE_PLATFORM_ANDROID + ApiLayerManifestFile::AddManifestFilesAndroid(type, manifest_files); +#endif // XR_USE_PLATFORM_ANDROID + return XR_SUCCESS; } diff --git a/thirdparty/openxr/src/loader/manifest_file.hpp b/thirdparty/openxr/src/loader/manifest_file.hpp index 0d04886d84..de0aab65c2 100644 --- a/thirdparty/openxr/src/loader/manifest_file.hpp +++ b/thirdparty/openxr/src/loader/manifest_file.hpp @@ -14,6 +14,7 @@ #include <memory> #include <string> #include <vector> +#include <iosfwd> #include <unordered_map> namespace Json { @@ -79,6 +80,8 @@ class RuntimeManifestFile : public ManifestFile { std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files); }; +using LibraryLocator = bool (*)(const std::string &json_filename, const std::string &library_path, std::string &out_combined_path); + // ApiLayerManifestFile class - // Responsible for finding and parsing API Layer-specific manifest files. class ApiLayerManifestFile : public ManifestFile { @@ -93,8 +96,19 @@ class ApiLayerManifestFile : public ManifestFile { 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::istream &json_stream, + LibraryLocator locate_library, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files); static void CreateIfValid(ManifestFileType type, const std::string &filename, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files); + /// @return false if we could not find the library. + static bool LocateLibraryRelativeToJson(const std::string &json_filename, const std::string &library_path, + std::string &out_combined_path); +#ifdef XR_USE_PLATFORM_ANDROID + static bool LocateLibraryInAssets(const std::string &json_filename, const std::string &library_path, + std::string &out_combined_path); + static void AddManifestFilesAndroid(ManifestFileType type, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files); +#endif JsonVersion _api_version; std::string _layer_name; diff --git a/thirdparty/openxr/src/loader/runtime_interface.cpp b/thirdparty/openxr/src/loader/runtime_interface.cpp index 1a35ba013a..0f081ff9b2 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.cpp +++ b/thirdparty/openxr/src/loader/runtime_interface.cpp @@ -27,6 +27,7 @@ #ifdef XR_USE_PLATFORM_ANDROID #include "android_utilities.h" +#include <android/asset_manager_jni.h> #include <json/value.h> #endif // XR_USE_PLATFORM_ANDROID @@ -50,6 +51,14 @@ class LoaderInitData { * Type alias for the platform-specific structure type. */ using StructType = XrLoaderInitInfoAndroidKHR; + /*! + * Native library path. + */ + std::string _native_library_path; + /*! + * Android asset manager. + */ + AAssetManager* _android_asset_manager; #endif /*! @@ -99,6 +108,30 @@ XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) { _data = *cast_info; jni::init((jni::JavaVM*)_data.applicationVM); _data.next = nullptr; + JNIEnv* Env; + ((jni::JavaVM*)(cast_info->applicationVM))->AttachCurrentThread(&Env, nullptr); + const jclass contextClass = Env->GetObjectClass((jobject)_data.applicationContext); + + const jmethodID getAssetsMethod = Env->GetMethodID(contextClass, "getAssets", "()Landroid/content/res/AssetManager;"); + const jobject AssetManagerObject = Env->CallObjectMethod((jobject)_data.applicationContext, getAssetsMethod); + _android_asset_manager = AAssetManager_fromJava(Env, AssetManagerObject); + + const jmethodID getApplicationContextMethod = + Env->GetMethodID(contextClass, "getApplicationContext", "()Landroid/content/Context;"); + const jobject contextObject = Env->CallObjectMethod((jobject)_data.applicationContext, getApplicationContextMethod); + const jmethodID getApplicationInfoMethod = + Env->GetMethodID(contextClass, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); + const jobject applicationInfoObject = Env->CallObjectMethod(contextObject, getApplicationInfoMethod); + const jfieldID nativeLibraryDirField = + Env->GetFieldID(Env->GetObjectClass(applicationInfoObject), "nativeLibraryDir", "Ljava/lang/String;"); + const jobject nativeLibraryDirObject = Env->GetObjectField(applicationInfoObject, nativeLibraryDirField); + const jmethodID getBytesMethod = + Env->GetMethodID(Env->GetObjectClass(nativeLibraryDirObject), "getBytes", "(Ljava/lang/String;)[B"); + const auto bytesObject = + static_cast<jbyteArray>(Env->CallObjectMethod(nativeLibraryDirObject, getBytesMethod, Env->NewStringUTF("UTF-8"))); + const size_t length = Env->GetArrayLength(bytesObject); + const jbyte* const bytes = Env->GetByteArrayElements(bytesObject, nullptr); + _native_library_path = std::string(reinterpret_cast<const char*>(bytes), length); _initialized = true; return XR_SUCCESS; } @@ -109,6 +142,10 @@ XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) { return LoaderInitData::instance().initialize(loaderInitInfo); } +std::string GetAndroidNativeLibraryDir() { return LoaderInitData::instance()._native_library_path; } + +void* Android_Get_Asset_Manager() { return LoaderInitData::instance()._android_asset_manager; } + #endif // XR_KHR_LOADER_INIT_SUPPORT #ifdef XR_USE_PLATFORM_ANDROID diff --git a/thirdparty/openxr/src/loader/runtime_interface.hpp b/thirdparty/openxr/src/loader/runtime_interface.hpp index 5f49b28abe..fa53ee03f2 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.hpp +++ b/thirdparty/openxr/src/loader/runtime_interface.hpp @@ -31,6 +31,8 @@ class Value; //! Initialize loader, where required. XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo); XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest); +std::string GetAndroidNativeLibraryDir(); +void* Android_Get_Asset_Manager(); #endif class RuntimeManifestFile; |