Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/openxr/src/loader/loader_instance.cpp')
-rw-r--r--extern/openxr/src/loader/loader_instance.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/extern/openxr/src/loader/loader_instance.cpp b/extern/openxr/src/loader/loader_instance.cpp
new file mode 100644
index 00000000000..67b0ee5be3e
--- /dev/null
+++ b/extern/openxr/src/loader/loader_instance.cpp
@@ -0,0 +1,235 @@
+// Copyright (c) 2017-2019 The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// 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>
+//
+
+#ifdef XR_OS_WINDOWS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#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>
+
+// Extensions that are supported by the loader, but may not be supported
+// the the runtime.
+static const XrExtensionProperties g_debug_utils_props = {XR_TYPE_EXTENSION_PROPERTIES, nullptr, XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
+ XR_EXT_debug_utils_SPEC_VERSION};
+const std::vector<XrExtensionProperties> LoaderInstance::_loader_supported_extensions = {g_debug_utils_props};
+
+// Factory method
+XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces,
+ const XrInstanceCreateInfo* info, XrInstance* instance) {
+ XrResult last_error = XR_SUCCESS;
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering LoaderInstance::CreateInstance");
+
+ // Topmost means "closest to the application"
+ PFN_xrCreateInstance topmost_ci_fp = LoaderXrTermCreateInstance;
+ PFN_xrCreateApiLayerInstance topmost_cali_fp = LoaderXrTermCreateApiLayerInstance;
+
+ // Create the loader instance
+ std::unique_ptr<LoaderInstance> loader_instance(new LoaderInstance(std::move(api_layer_interfaces)));
+ *instance = reinterpret_cast<XrInstance>(loader_instance.get());
+
+ // Only start the xrCreateApiLayerInstance stack if we have layers.
+ std::vector<std::unique_ptr<ApiLayerInterface>>& layer_interfaces = loader_instance->LayerInterfaces();
+ if (!layer_interfaces.empty()) {
+ // Initialize an array of ApiLayerNextInfo structs
+ auto* next_info_list = new XrApiLayerNextInfo[layer_interfaces.size()];
+ auto ni_index = static_cast<uint32_t>(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.
+ XrApiLayerNextInfo* prev_nextinfo = nullptr;
+ PFN_xrGetInstanceProcAddr prev_gipa_fp = LoaderXrTermGetInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance prev_cali_fp = LoaderXrTermCreateApiLayerInstance;
+ for (auto layer_interface = layer_interfaces.rbegin(); layer_interface != 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();
+ // Update topmosts
+ cur_gipa_fp(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&topmost_ci_fp));
+ topmost_cali_fp = cur_cali_fp;
+
+ // 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 = prev_nextinfo;
+ next_info_list[ni_index].nextGetInstanceProcAddr = prev_gipa_fp;
+ next_info_list[ni_index].nextCreateApiLayerInstance = prev_cali_fp;
+
+ // Update saved pointers for next iteration
+ prev_nextinfo = &next_info_list[ni_index];
+ prev_gipa_fp = cur_gipa_fp;
+ prev_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 = reinterpret_cast<void*>(loader_instance.get());
+ api_layer_ci.settings_file_location[0] = '\0';
+ api_layer_ci.nextInfo = next_info_list;
+ last_error = topmost_cali_fp(info, &api_layer_ci, instance);
+
+ delete[] next_info_list;
+ } else {
+ last_error = topmost_ci_fp(info, instance);
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ // Check the list of enabled extensions to make sure something supports them, and, if we do,
+ // add it to the list of enabled extensions
+ 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::_loader_supported_extensions) {
+ if (strcmp(loader_extension.extensionName, info->enabledExtensionNames[ext]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ }
+ // Finally, check the enabled layers
+ if (!found) {
+ for (auto& layer_interface : 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;
+ }
+ loader_instance->AddEnabledExtension(info->enabledExtensionNames[ext]);
+ }
+ } else {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "LoaderInstance::CreateInstance chained CreateInstance call failed");
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ // Create the top-level dispatch table for the instance. This will contain the function pointers to the
+ // first instantiation of every command, whether that is in a layer, or a runtime.
+ last_error = loader_instance->CreateDispatchTable(*instance);
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance",
+ "LoaderInstance::CreateInstance failed creating top-level dispatch table");
+ } else {
+ last_error = g_instance_map.Insert(*instance, *loader_instance);
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance",
+ "LoaderInstance::CreateInstance failed inserting new instance into map: may be null or not unique");
+ }
+ }
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ std::ostringstream oss;
+ oss << "LoaderInstance::CreateInstance succeeded with ";
+ oss << loader_instance->LayerInterfaces().size();
+ oss << " layers enabled and runtime interface - created instance = ";
+ oss << HandleToHexString(*instance);
+ LoaderLogger::LogInfoMessage("xrCreateInstance", oss.str());
+ // Make the unique_ptr no longer delete this.
+ // Don't need to save the return value because we already set *instance
+ (void)loader_instance.release();
+ }
+
+ // Always clear the input lists. Either we use them or we don't.
+ api_layer_interfaces.clear();
+
+ return last_error;
+}
+
+LoaderInstance::LoaderInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces)
+ : _unique_id(0xDECAFBAD),
+ _api_version(XR_CURRENT_API_VERSION),
+ _api_layer_interfaces(std::move(api_layer_interfaces)),
+ _dispatch_valid(false),
+ _messenger(XR_NULL_HANDLE) {}
+
+LoaderInstance::~LoaderInstance() {
+ std::ostringstream oss;
+ oss << "Destroying LoaderInstance = ";
+ oss << PointerToHexString(this);
+ LoaderLogger::LogInfoMessage("xrDestroyInstance", oss.str());
+}
+
+XrResult LoaderInstance::CreateDispatchTable(XrInstance instance) {
+ XrResult res = XR_SUCCESS;
+ // Create the top-level dispatch table. First, we want to start with a dispatch table generated
+ // using the commands from the runtime, with the exception of commands that we need a terminator
+ // for. The loaderGenInitInstanceDispatchTable utility function handles that automatically for us.
+ std::unique_ptr<XrGeneratedDispatchTable> new_instance_dispatch_table(new XrGeneratedDispatchTable());
+ LoaderGenInitInstanceDispatchTable(_runtime_instance, new_instance_dispatch_table);
+
+ // 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.
+ if (!_api_layer_interfaces.empty()) {
+ (*_api_layer_interfaces.begin())->GenUpdateInstanceDispatchTable(instance, new_instance_dispatch_table);
+ }
+
+ // Set the top-level instance dispatch table to the top-most commands now that we've figured them out.
+ _dispatch_table = std::move(new_instance_dispatch_table);
+ _dispatch_valid = true;
+ return res;
+}
+
+bool LoaderInstance::ExtensionIsEnabled(const std::string& extension) {
+ for (std::string& cur_enabled : _enabled_extensions) {
+ if (cur_enabled == extension) {
+ return true;
+ }
+ }
+ return false;
+}