上传YomovSDK
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
#if XR_COMPOSITION_LAYERS
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.XR.CompositionLayers.Extensions;
|
||||
using Unity.XR.CompositionLayers.Layers;
|
||||
using Unity.XR.CompositionLayers.Services;
|
||||
using UnityEngine.XR.OpenXR.NativeTypes;
|
||||
#if UNITY_VIDEO
|
||||
using UnityEngine.Video;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.CompositionLayers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base implementation for the <see cref="OpenXRLayerProvider.ILayerHandler"/> interface.
|
||||
/// You can implement the required methods of this abstract class to create a concrete layer handler.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="OpenXRLayerProvider.ILayerHandler"/> methods that this class implements handle adding
|
||||
/// and removing composition layers from native arrays, swap chain creation dispatching and other tasks
|
||||
/// required by the Unity side of the API.
|
||||
///
|
||||
/// The abstract methods that you must implement handle the custom aspects of your layer. These methods include:
|
||||
///
|
||||
/// * <see cref="CreateSwapchain(CompositionLayerManager.LayerInfo, out SwapchainCreateInfo)"/>
|
||||
/// * <see cref="CreateNativeLayer(CompositionLayerManager.LayerInfo, OpenXRCustomLayerHandler{T}.SwapchainCreatedOutput, out T)"/>
|
||||
/// * <see cref="ModifyNativeLayer(CompositionLayerManager.LayerInfo, ref T)"/>
|
||||
///
|
||||
/// You are not required to implement a custom layer handler based on this abstract class, but doing so should be
|
||||
/// easier than implementing the <see cref="OpenXRLayerProvider.ILayerHandler"/> interface in its entirety.
|
||||
///
|
||||
/// You must register your concrete layer handler object with
|
||||
/// <see cref="OpenXRLayerProvider.RegisterLayerHandler(Type, OpenXRLayerProvider.ILayerHandler)"/>.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">The native OpenXR structure of the composition layer to handle.</typeparam>
|
||||
public abstract class OpenXRCustomLayerHandler<T> : OpenXRLayerProvider.ILayerHandler, IDisposable where T : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Container for swapchain related information that may be needed during the creation of the native OpenXR composition layer struct.
|
||||
/// </summary>
|
||||
protected struct SwapchainCreateInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Native structure for the swapchain creation info.
|
||||
/// </summary>
|
||||
public XrSwapchainCreateInfo nativeStruct;
|
||||
|
||||
/// <summary>
|
||||
/// Tells if swapchain is using an external surface.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool isExternalSurface;
|
||||
|
||||
/// <summary>
|
||||
/// Tells if swapchain should be stereo.
|
||||
/// </summary>
|
||||
public bool isStereo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of SwapchainCreateInfo with the provided parameters.
|
||||
/// </summary>
|
||||
/// <param name="xrSwapchainCreateInfo">Native structure for the swapchain creation info.</param>
|
||||
/// <param name="isExternalSurface">Tells if swapchain is using an external surface.</param>
|
||||
/// <param name="isStereo">Tells if swapchain should be stereo.</param>
|
||||
public SwapchainCreateInfo(XrSwapchainCreateInfo xrSwapchainCreateInfo, bool isExternalSurface = false, bool isStereo = false)
|
||||
{
|
||||
this.nativeStruct = xrSwapchainCreateInfo;
|
||||
this.isExternalSurface = isExternalSurface;
|
||||
this.isStereo = isStereo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion with just a native XrSwapchainCreateInfo struct.
|
||||
/// </summary>
|
||||
/// <param name="createInfo">The native struct to convert.</param>
|
||||
public static implicit operator SwapchainCreateInfo(XrSwapchainCreateInfo createInfo) => new SwapchainCreateInfo(createInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Container for swapchain related information that may be needed during the creation of the native OpenXR composition layer struct.
|
||||
/// </summary>
|
||||
protected struct SwapchainCreatedOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// The handle of the created swapchain.
|
||||
/// Can be used to initialize the swapchain member of a native OpenXR composition layer struct.
|
||||
/// </summary>
|
||||
public ulong handle;
|
||||
|
||||
/// <summary>
|
||||
/// The second handle of the created stereo swapchain.
|
||||
/// Can be used to initialize the swapchain member of a native OpenXR composition layer struct.
|
||||
/// </summary>
|
||||
public ulong secondStereoHandle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Container for grouping render information for each compostion layer.
|
||||
/// </summary>
|
||||
class LayerRenderInfo
|
||||
{
|
||||
public RenderTexture RenderTexture;
|
||||
public Texture Texture;
|
||||
#if UNITY_VIDEO
|
||||
public VideoPlayer videoPlayer;
|
||||
#endif
|
||||
public MeshCollider meshCollider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of this <c>OpenXRCustomLayerHandler<T></c> while also setting the singleton instance member.
|
||||
/// </summary>
|
||||
protected OpenXRCustomLayerHandler() => Instance = this;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance of this specific handler.
|
||||
/// </summary>
|
||||
protected static OpenXRCustomLayerHandler<T> Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Deinitializes this instance of c>OpenXRCustomLayerHandler<T></c>.
|
||||
/// </summary>
|
||||
~OpenXRCustomLayerHandler() => Dispose(false);
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to create the <see cref="XrSwapchainCreateInfo"/> struct that is passed to OpenXR
|
||||
/// to create a swapchain.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To add extensions when constructing the <see cref="XrSwapchainCreateInfo"/> struct, initialize
|
||||
/// the <c>Next</c> pointer with
|
||||
/// <see cref="OpenXRLayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// Constructs an XrSwapchainCreateInfo struct with some members using component data.
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// protected override bool CreateSwapchain(CompositionLayerManager.LayerInfo layerInfo, out SwapchainCreateInfo swapchainCreateInfo)
|
||||
/// {
|
||||
/// var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
|
||||
/// unsafe
|
||||
/// {
|
||||
/// swapchainCreateInfo = new XrSwapchainCreateInfo()
|
||||
/// {
|
||||
/// Type = (uint)XrStructureType.XR_TYPE_SWAPCHAIN_CREATE_INFO,
|
||||
/// Next = OpenXRLayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Swapchain),
|
||||
/// CreateFlags = 0,
|
||||
/// UsageFlags = (ulong)(XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XrSwapchainUsageFlags.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT),
|
||||
/// Format = OpenXRLayerUtility.GetDefaultColorFormat(),
|
||||
/// SampleCount = 1,
|
||||
/// Width = (uint)texturesExtension.LeftTexture.width,
|
||||
/// Height = (uint)texturesExtension.LeftTexture.height,
|
||||
/// FaceCount = 1,
|
||||
/// ArraySize = 1,
|
||||
/// MipCount = (uint)texturesExtension.LeftTexture.mipmapCount,
|
||||
/// };
|
||||
/// }
|
||||
/// return true;
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// that was just created.</param>
|
||||
/// <param name="swapchainCreateInfo"> An <c>XrSwapchainCreateInfo</c> object created and initialized by the concrete implementation of this method.</returns>
|
||||
/// <returns> A bool indicating success or failure.</returns>
|
||||
|
||||
protected abstract bool CreateSwapchain(CompositionLayerManager.LayerInfo layerInfo, out SwapchainCreateInfo swapchainCreateInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to create the native composition layer struct of type T that is passed to OpenXR.
|
||||
/// A swapchain info struct is provided so your layer handler has access to any needed swapchain information.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To add extensions when constructing the <see cref="XrSwapchainCreateInfo"/> struct, initialize
|
||||
/// the <c>Next</c> pointer with <see cref="OpenXRLayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>.
|
||||
///
|
||||
/// If your struct needs any XrSpace relative info you can use <see cref="OpenXRLayerUtility.GetCurrentAppSpace"/>
|
||||
/// to get the current app space.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// Constructs an XrCompositionLayerQuad struct with some members using component data.
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// protected override bool CreateNativeLayer(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput, out XrCompositionLayerQuad nativeLayer)
|
||||
/// {
|
||||
/// var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
|
||||
/// var transform = layerInfo.Layer.GetComponent<Transform>();
|
||||
///
|
||||
/// unsafe
|
||||
/// {
|
||||
/// var data = layerInfo.Layer.LayerData as QuadLayerData;
|
||||
///
|
||||
/// nativeLayer = new XrCompositionLayerQuad()
|
||||
/// {
|
||||
/// Type = 36,
|
||||
/// Next = OpenXRLayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer),
|
||||
/// LayerFlags = 0x00000002,
|
||||
/// Space = OpenXRLayerUtility.GetCurrentAppSpace(),
|
||||
/// EyeVisibility = 0,
|
||||
/// SubImage = new SwapchainSubImage()
|
||||
/// {
|
||||
/// Swapchain = swapchainOutput.handle,
|
||||
/// ImageRect = new XrRect2Di()
|
||||
/// {
|
||||
/// offset = new XrOffset2Di() { x = 0, y = 0 },
|
||||
/// extent = new XrExtent2Di()
|
||||
/// {
|
||||
/// width = texturesExtension.LeftTexture.width,
|
||||
/// height = texturesExtension.LeftTexture.height
|
||||
/// }
|
||||
/// },
|
||||
/// ImageArrayIndex = 0
|
||||
/// },
|
||||
/// Pose = new XrPosef(transform.position, transform.rotation),
|
||||
/// Size = new XrExtend2Df()
|
||||
/// {
|
||||
/// width = data.GetScaledSize(transform.lossyScale).x,
|
||||
/// height = data.GetScaledSize(transform.lossyScale).y
|
||||
/// }
|
||||
/// };
|
||||
/// }
|
||||
/// return true;
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// that was just created.</param>
|
||||
/// <param name="swapchainOutput"> Information regarding the swapchain that was created for this layer,
|
||||
/// such as the associated swapchain handle.</param>
|
||||
/// <param name="nativeLayer"> An object of type T that is created and initialized by the concrete implementation of this method.</returns>
|
||||
/// <returns> A bool indicating success or failure.</returns>
|
||||
|
||||
protected abstract bool CreateNativeLayer(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput, out T nativeLayer);
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to modify a native composition layer struct in response to changes on the associated
|
||||
/// <see cref="Unity.XR.CompositionLayers.Layers.LayerData"/> object or any extension components on the
|
||||
/// <see cref="Unity.XR.CompositionLayers.CompositionLayer"/> GameObject.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You must reinitialize the Next pointer with <see cref="OpenXRLayerUtility.GetExtensionsChain(CompositionLayerManager.LayerInfo, Unity.XR.CompositionLayers.CompositionLayerExtension.ExtensionTarget)"/>
|
||||
/// to get any potential updates from extension components.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// Modifies an XrCompositionLayerQuad struct with new transform and extension information.
|
||||
/// <code>
|
||||
/// <![CDATA[
|
||||
/// protected override bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref XrCompositionLayerQuad nativeLayer)
|
||||
/// {
|
||||
/// var data = layerInfo.Layer.LayerData as QuadLayerData;
|
||||
/// var transform = layerInfo.Layer.GetComponent<Transform>();
|
||||
///
|
||||
/// nativeLayer.Pose = new XrPosef(transform.position, transform.rotation);
|
||||
/// nativeLayer.Size = new XrExtend2Df()
|
||||
/// {
|
||||
/// width = data.GetScaledSize(transform.lossyScale).x,
|
||||
/// height = data.GetScaledSize(transform.lossyScale).y
|
||||
/// };
|
||||
///
|
||||
/// unsafe
|
||||
/// {
|
||||
/// nativeLayer.Next = OpenXRLayerUtility.GetExtensionsChain(layerInfo, CompositionLayerExtension.ExtensionTarget.Layer);
|
||||
/// }
|
||||
/// return true;
|
||||
/// }
|
||||
/// ]]>
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition
|
||||
/// layer that was modified.</param>
|
||||
/// <param name="nativeLayer"> A reference to the native OpenXR structure of the composition layer that was modified.
|
||||
/// The concrete implementation of this method should update the values of the structure as appropriate.</param>
|
||||
/// <returns> A bool indicating success or failure.</returns>
|
||||
protected abstract bool ModifyNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref T nativeLayer);
|
||||
|
||||
/// <summary>
|
||||
/// Mapping of instance ids and native layer structs to help determine what layers are currently set to be active.
|
||||
/// </summary>
|
||||
protected Dictionary<int, T> m_nativeLayers = new Dictionary<int, T>();
|
||||
|
||||
/// <summary>
|
||||
/// Thread safe queue used to dispatch callbacks that may come from other threads such as the swapchain creation
|
||||
/// on the graphics thread.
|
||||
/// </summary>
|
||||
protected ConcurrentQueue<Action> actionsForMainThread = new ConcurrentQueue<Action>();
|
||||
|
||||
Dictionary<int, LayerRenderInfo> m_renderInfos = new Dictionary<int, LayerRenderInfo>();
|
||||
Dictionary<int, CompositionLayerManager.LayerInfo> m_layerInfos = new Dictionary<int, CompositionLayerManager.LayerInfo>();
|
||||
NativeArray<T> m_ActiveNativeLayers;
|
||||
NativeArray<int> m_ActiveNativeLayerOrders;
|
||||
int m_ActiveNativeLayerCount;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="OpenXRLayerProvider.ILayerHandler"/> method that is called by the
|
||||
/// <see cref="OpenXRLayerProvider"/> during the Unity update loop.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation carries out two tasks. It dequeues actions for the main thread like dispatch when
|
||||
/// the swapchain has been
|
||||
/// created and it adds all the active layers to the <c>endFrameInfo</c> struct in the native UnityOpenXR lib.
|
||||
/// </remarks>
|
||||
public virtual void OnUpdate()
|
||||
{
|
||||
while (actionsForMainThread.Count > 0)
|
||||
{
|
||||
if (actionsForMainThread.TryDequeue(out Action action))
|
||||
action();
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
if (m_ActiveNativeLayerCount > 0)
|
||||
OpenXRLayerUtility.AddActiveLayersToEndFrame(m_ActiveNativeLayers.GetUnsafePtr(), m_ActiveNativeLayerOrders.GetUnsafePtr(), m_ActiveNativeLayerCount, UnsafeUtility.SizeOf<T>());
|
||||
}
|
||||
|
||||
m_ActiveNativeLayerCount = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="OpenXRLayerProvider.ILayerHandler"/> method that is called by the
|
||||
/// <see cref="OpenXRLayerProvider"/> when a new layer has been created.
|
||||
/// This implementation triggers the creation of a swapchain before the actual native layer struct is created.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// being created.</param>
|
||||
public void CreateLayer(CompositionLayerManager.LayerInfo layerInfo)
|
||||
{
|
||||
CreateSwapchainAsync(layerInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="OpenXRLayerProvider.ILayerHandler"/> method that is called by the
|
||||
/// <see cref="OpenXRLayerProvider"/> when a layer or attached extension has been modified.
|
||||
/// This implementation asks the subclass for any changes that must be made to the layer via
|
||||
/// <see cref="ModifyNativeLayer(CompositionLayerManager.LayerInfo, ref T)"/>
|
||||
/// by sending a reference to the native layer struct.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// that was modified.</param>
|
||||
public virtual void ModifyLayer(CompositionLayerManager.LayerInfo layerInfo)
|
||||
{
|
||||
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
|
||||
|
||||
if (!m_nativeLayers.TryGetValue(layerInfo.Id, out var nativeLayer))
|
||||
{
|
||||
if (texturesExtension != null && texturesExtension.TextureAdded)
|
||||
{
|
||||
texturesExtension.TextureAdded = false;
|
||||
CreateLayer(layerInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var success = ModifyNativeLayer(layerInfo, ref nativeLayer);
|
||||
if (success)
|
||||
m_nativeLayers[layerInfo.Id] = nativeLayer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="OpenXRLayerProvider.ILayerHandler"/> method that is called by the
|
||||
/// <see cref="OpenXRLayerProvider"/> when a layer is destroyed or disabled.
|
||||
/// </summary>
|
||||
/// <param name="removedLayerId"> The instance id of the CompositionLayer component that was removed.</param>
|
||||
public virtual void RemoveLayer(int removedLayerId)
|
||||
{
|
||||
OpenXRLayerUtility.ReleaseSwapchain(removedLayerId);
|
||||
m_nativeLayers.Remove(removedLayerId);
|
||||
m_layerInfos.Remove(removedLayerId);
|
||||
m_renderInfos.Remove(removedLayerId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="OpenXRLayerProvider.ILayerHandler"/> method that is called by the
|
||||
/// <see cref="OpenXRLayerProvider"/> when a layer is considered to be currently active.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// being set to active.</param>
|
||||
public virtual void SetActiveLayer(CompositionLayerManager.LayerInfo layerInfo)
|
||||
{
|
||||
if (!m_nativeLayers.TryGetValue(layerInfo.Id, out var nativeLayer))
|
||||
return;
|
||||
|
||||
var success = ActiveNativeLayer(layerInfo, ref nativeLayer);
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
m_nativeLayers[layerInfo.Id] = nativeLayer;
|
||||
ResizeNativeArrays();
|
||||
m_ActiveNativeLayers[m_ActiveNativeLayerCount] = m_nativeLayers[layerInfo.Id];
|
||||
m_ActiveNativeLayerOrders[m_ActiveNativeLayerCount] = layerInfo.Layer.Order;
|
||||
++m_ActiveNativeLayerCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements method from <see cref="IDisposable"/> that is called by the <see cref="OpenXRLayerProvider"/>
|
||||
/// when this custom layer handler instance is disposed.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all maps and disposes any created native arrays.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Determines if this method was called from the Dispose() method or the finalizer.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_layerInfos.Clear();
|
||||
m_nativeLayers.Clear();
|
||||
m_renderInfos.Clear();
|
||||
}
|
||||
|
||||
if (m_ActiveNativeLayers.IsCreated)
|
||||
m_ActiveNativeLayers.Dispose();
|
||||
if (m_ActiveNativeLayerOrders.IsCreated)
|
||||
m_ActiveNativeLayerOrders.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="CreateSwapchain(CompositionLayerManager.LayerInfo, out SwapchainCreateInfo)"/> to create a
|
||||
/// <see cref="SwapchainCreateInfo"/> struct that is then passed to the
|
||||
/// UnityOpenXR lib to actually create the swapchain on the graphics thread.
|
||||
/// The static <see cref="OnCreatedSwapchainCallback(int, ulong)"/> method is passed as a callback and invoked when
|
||||
/// the swapchain has been created.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// that was just created.</param>
|
||||
protected virtual void CreateSwapchainAsync(CompositionLayerManager.LayerInfo layerInfo)
|
||||
{
|
||||
m_layerInfos[layerInfo.Id] = layerInfo;
|
||||
var success = CreateSwapchain(layerInfo, out var swapChainInfo);
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
if (swapChainInfo.isStereo)
|
||||
OpenXRLayerUtility.CreateStereoSwapchain(layerInfo.Id, swapChainInfo.nativeStruct, OnCreatedStereoSwapchainCallback);
|
||||
else
|
||||
OpenXRLayerUtility.CreateSwapchain(layerInfo.Id, swapChainInfo.nativeStruct, swapChainInfo.isExternalSurface, OnCreatedSwapchainCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is dispatched to the main thread inside <see cref="OnCreatedSwapchainCallback(int, ulong)"/>
|
||||
/// and asks this subclass to create the native layer struct by invoking
|
||||
/// <see cref="CreateNativeLayer(CompositionLayerManager.LayerInfo, SwapchainCreatedOutput, out T)"/>.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition layer
|
||||
/// that was just created.</param>
|
||||
/// <param name="swapchainOutput"> Information regarding the swapchain that was created for this layer, such as
|
||||
/// the associated swapchain handle.</param>
|
||||
protected virtual void OnCreatedSwapchain(CompositionLayerManager.LayerInfo layerInfo, SwapchainCreatedOutput swapchainOutput)
|
||||
{
|
||||
var success = CreateNativeLayer(layerInfo, swapchainOutput, out var nativeLayer);
|
||||
if (success)
|
||||
m_nativeLayers[layerInfo.Id] = nativeLayer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the native arrays are of the same size as the m_nativeLayers map.
|
||||
/// </summary>
|
||||
protected virtual void ResizeNativeArrays()
|
||||
{
|
||||
if (!m_ActiveNativeLayers.IsCreated && !m_ActiveNativeLayerOrders.IsCreated)
|
||||
{
|
||||
m_ActiveNativeLayers = new NativeArray<T>(m_nativeLayers.Count, Allocator.Persistent);
|
||||
m_ActiveNativeLayerOrders = new NativeArray<int>(m_nativeLayers.Count, Allocator.Persistent);
|
||||
return;
|
||||
}
|
||||
|
||||
Assertions.Assert.AreEqual(m_ActiveNativeLayers.Length, m_ActiveNativeLayerOrders.Length);
|
||||
|
||||
if (m_ActiveNativeLayers.Length < m_nativeLayers.Count)
|
||||
{
|
||||
var newLayerArray = new NativeArray<T>(m_nativeLayers.Count, Allocator.Persistent);
|
||||
NativeArray<T>.Copy(m_ActiveNativeLayers, newLayerArray, m_ActiveNativeLayers.Length);
|
||||
m_ActiveNativeLayers.Dispose();
|
||||
m_ActiveNativeLayers = newLayerArray;
|
||||
|
||||
var newOrderArray = new NativeArray<int>(m_nativeLayers.Count, Allocator.Persistent);
|
||||
NativeArray<int>.Copy(m_ActiveNativeLayerOrders, newOrderArray, m_ActiveNativeLayerOrders.Length);
|
||||
m_ActiveNativeLayerOrders.Dispose();
|
||||
m_ActiveNativeLayerOrders = newOrderArray;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to modify a native composition layer struct in response to when it is active.
|
||||
/// An active compositon layer will invoke this every frame.
|
||||
/// </summary>
|
||||
/// <param name="layerInfo"> Container for the instance id and CompositionLayer component of the composition
|
||||
/// layer that is active.</param>
|
||||
/// <param name="nativeLayer"> A reference to the native OpenXR structure of the composition layer that is active.</param>
|
||||
/// <returns>Bool indicating success or failure. A failure case will result in the native composition layer struct not being added into the final XrFrameEndInfo struct.</returns>
|
||||
protected virtual bool ActiveNativeLayer(CompositionLayerManager.LayerInfo layerInfo, ref T nativeLayer)
|
||||
{
|
||||
var texturesExtension = layerInfo.Layer.GetComponent<TexturesExtension>();
|
||||
if (texturesExtension == null || texturesExtension.LeftTexture == null || texturesExtension.sourceTexture == TexturesExtension.SourceTextureEnum.AndroidSurface)
|
||||
return true;
|
||||
|
||||
if (m_renderInfos.TryGetValue(layerInfo.Id, out var container))
|
||||
{
|
||||
bool isNewTexture = container.Texture != texturesExtension.LeftTexture;
|
||||
|
||||
if (isNewTexture)
|
||||
{
|
||||
// If we have a new texture with different dimensions then we need to release the current swapchain and create another.
|
||||
// This is an async procedure that also creates a new native layer object.
|
||||
if (container.Texture.width != texturesExtension.LeftTexture.width || container.Texture.height != texturesExtension.LeftTexture.height)
|
||||
{
|
||||
RemoveLayer(layerInfo.Id);
|
||||
CreateSwapchainAsync(layerInfo);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
container.Texture = texturesExtension.LeftTexture;
|
||||
#if UNITY_VIDEO
|
||||
container.videoPlayer = layerInfo.Layer.GetComponent<VideoPlayer>();
|
||||
#endif
|
||||
container.meshCollider = layerInfo.Layer.GetComponent<MeshCollider>();
|
||||
}
|
||||
|
||||
bool isVideo = false;
|
||||
#if UNITY_VIDEO
|
||||
isVideo = container.videoPlayer != null && container.videoPlayer.enabled;
|
||||
#endif
|
||||
bool isUI = container.meshCollider != null && container.meshCollider.enabled;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Layers with a video or ui component in editor may have multiple native render textures associated with the layer id so we must find them.
|
||||
if (isVideo || isUI)
|
||||
OpenXRLayerUtility.FindAndWriteToRenderTexture(layerInfo, container.Texture, out container.RenderTexture);
|
||||
else if (isNewTexture)
|
||||
OpenXRLayerUtility.WriteToRenderTexture(container.Texture, container.RenderTexture);
|
||||
#else
|
||||
// We only need to write continuously to the native render texture if our texture is changing.
|
||||
if (isVideo || isUI || isNewTexture)
|
||||
OpenXRLayerUtility.WriteToRenderTexture(container.Texture, container.RenderTexture);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
bool isRenderTextureWritten = OpenXRLayerUtility.FindAndWriteToRenderTexture(layerInfo, texturesExtension.LeftTexture, out RenderTexture renderTexture);
|
||||
if (isRenderTextureWritten)
|
||||
{
|
||||
var layerRenderInfo = new LayerRenderInfo()
|
||||
{ Texture = texturesExtension.LeftTexture, RenderTexture = renderTexture,
|
||||
#if UNITY_VIDEO
|
||||
videoPlayer = layerInfo.Layer.GetComponent<VideoPlayer>(),
|
||||
#endif
|
||||
meshCollider = layerInfo.Layer.GetComponent<MeshCollider>() };
|
||||
m_renderInfos.Add(layerInfo.Id, layerRenderInfo);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OpenXRLayerUtility.SwapchainCallbackDelegate))]
|
||||
static void OnCreatedSwapchainCallback(int layerId, ulong swapchainHandle)
|
||||
{
|
||||
if (Instance == null)
|
||||
return;
|
||||
|
||||
Instance.actionsForMainThread.Enqueue(() => { Instance.OnCreatedSwapchain(Instance.m_layerInfos[layerId], new SwapchainCreatedOutput { handle = swapchainHandle });});
|
||||
}
|
||||
|
||||
[AOT.MonoPInvokeCallback(typeof(OpenXRLayerUtility.StereoSwapchainCallbackDelegate))]
|
||||
static void OnCreatedStereoSwapchainCallback(int layerId, ulong swapchainHandleLeft, ulong swapchainHandleRight)
|
||||
{
|
||||
if (Instance == null)
|
||||
return;
|
||||
|
||||
Instance.actionsForMainThread.Enqueue(() => { Instance.OnCreatedSwapchain(Instance.m_layerInfos[layerId], new SwapchainCreatedOutput { handle = swapchainHandleLeft, secondStereoHandle = swapchainHandleRight}); });
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user