// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; using System.Collections.Generic; using UnityEngine.XR.OpenXR; namespace Microsoft.MixedReality.OpenXR { [AttributeUsage(AttributeTargets.Class)] public class RequiresNativePluginDLLsAttribute : Attribute { } // A utility for managing connections between Mixed Reality OpenXR feature plugins and the native plugin DLL. internal static class OpenXRFeaturePluginManager { // If this is true, the NativeLib is guaranteed to be available. // If this is false, the NativeLib may or may not be available. internal static bool NativeLibAvailable { get => m_nativeLibAvailable; } private static bool m_nativeLibAvailable = false; // Cache the result of all enabled OpenXRSettings.Instance.GetFeatures() in our package. // The first element in the list will serve as the active feature for routing states to native library. // This list is updated at query for PFN_xrGetInstanceProcAddr, which is openxr_loader first load the runtime. private static List m_enabledPluginFeatures = new List(); // ActiveFeature is one of the enabled OpenXRFeature, when not null, it's in sync with OpenXR runtime status. internal static OpenXRFeaturePlugin ActiveFeature => m_enabledPluginFeatures.Count > 0 ? m_enabledPluginFeatures[0] : null; // Because Unity's OpenXRFeature notifies child classes about OpenXR state changes // always in a loop. reference: OpenXRFeature.cs, ReceiveNativeEvent() function. // To update our nativeLib, only one of such sync function is enough. // Choose the 1st enabled feature related to nativeLib as the responsible child class. internal static bool IsResponsibleForNativeLib(OpenXRFeaturePlugin plugin) { return m_enabledPluginFeatures.Count > 0 ? m_enabledPluginFeatures[0] == plugin : false; } internal static void OnFeaturePluginInitializing(OpenXRFeaturePlugin feature) { if (!m_nativeLibAvailable) { TryInitializeNativeLibAvailable(feature.GetType()); } } internal static void TryInitializeNativeLibAvailable(Type featureType) { if (!m_nativeLibAvailable) { var feature = OpenXRSettings.Instance.GetFeature(featureType); if (feature != null && feature.enabled && Attribute.IsDefined(featureType, typeof(RequiresNativePluginDLLsAttribute))) { m_nativeLibAvailable = true; } } } internal static void InitializeOpenXRFeatureList() { m_enabledPluginFeatures.Clear(); var features = OpenXRSettings.Instance.GetFeatures(typeof(OpenXRFeaturePlugin)); foreach (var pluginFeature in features) { if (pluginFeature != null && pluginFeature.enabled) { m_enabledPluginFeatures.Add((OpenXRFeaturePlugin)pluginFeature); NativeLib.InitializePluginProviders(pluginFeature.GetType().Name); } } } } }