// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2022) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
using System.Runtime.InteropServices;
namespace UnityEngine.XR.MagicLeap
{
public partial class MLNativeSurface
{
public enum PixelFormat
{
/*! Custom */
Custom = -4,
/*! Translucent */
Translucent = -3,
/*! Transparent */
Transparent = -2,
/*! Opaque */
Opaque = -1,
/*! None */
None = 0,
/*! 4x8-bit RGBA */
Rgba8888 = 1,
/*! 4x8-bit RGBX */
Rgbx8888 = 2,
/*! 3x8-bit RGB */
Rgb888 = 3,
/*! 16-bit RGB */
Rgb565 = 4,
/*! 4x8-bit BGRA */
Bgra8888 = 5,
/*! 64-bit RGBA */
RgbaFp16 = 22,
/*! 32-bit RGBA */
Rgba1010102 = 43,
}
public delegate void OnFrameAvailableDelegate();
public ulong Handle { get; private set; }
public event OnFrameAvailableDelegate OnFrameAvailable = delegate { };
private GCHandle gcHandle;
private readonly bool isExternallyOwned;
public MLNativeSurface(PixelFormat pixelFormat, ushort bufferCount, uint width, uint height)
{
gcHandle = GCHandle.Alloc(this, GCHandleType.Weak);
isExternallyOwned = false;
Handle = Native.MagicLeapNativeBindings.InvalidHandle;
NativeBindings.MLNativeSurfaceConfig config = new NativeBindings.MLNativeSurfaceConfig(pixelFormat, bufferCount, width, height);
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceCreate(ref config, out ulong nativeSurfaceHandle);
if (MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceCreate)))
{
Handle = nativeSurfaceHandle;
NativeBindings.MLNativeSurfaceOnFrameAvailableCallback frameInfo = NativeBindings.MLNativeSurfaceOnFrameAvailableCallback.Create();
resultCode = NativeBindings.MLNativeSurfaceSetOnFrameAvailableCallback(Handle, ref frameInfo, GCHandle.ToIntPtr(gcHandle));
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceSetOnFrameAvailableCallback));
}
}
///
/// For externally owned native surface, like in the case of MLMediaRecorder
///
///
public MLNativeSurface(ulong surfaceHandle)
{
Handle = surfaceHandle;
isExternallyOwned = true;
}
~MLNativeSurface()
{
Destroy();
}
public MLResult Destroy()
{
MLResult.Code resultCode = MLResult.Code.NotImplemented;
if (!isExternallyOwned)
{
if (gcHandle.IsAllocated)
{
gcHandle.Free();;
}
if (Native.MagicLeapNativeBindings.MLHandleIsValid(Handle))
{
resultCode = NativeBindings.MLNativeSurfaceRelease(Handle);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceRelease));
Handle = Native.MagicLeapNativeBindings.InvalidHandle;
}
}
return MLResult.Create(resultCode);
}
public MLResult AcquireNextAvailableFrame(out ulong nativeBuffer)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceAcquireNextAvailableFrame(Handle, out nativeBuffer);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceAcquireNextAvailableFrame));
return MLResult.Create(resultCode);
}
public MLResult ReleaseFrame(ulong nativeBuffer)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceReleaseFrame(Handle, nativeBuffer);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceReleaseFrame));
return MLResult.Create(resultCode);
}
public MLResult GetFrameTransformMatrix(float[] frameTransformMatColMajor)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceGetFrameTransformationMatrix(Handle, frameTransformMatColMajor);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceGetFrameTransformationMatrix));
return MLResult.Create(resultCode);
}
public MLResult GetFrameTimestamp(out long timestampNs)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceGetFrameTimestamp(Handle, out timestampNs);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceGetFrameTimestamp));
return MLResult.Create(resultCode);
}
public MLResult GetFrameQueueBufferTimestamp(out long timestampNs)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceGetFrameQueueBufferTimestamp(Handle, out timestampNs);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceGetFrameQueueBufferTimestamp));
return MLResult.Create(resultCode);
}
public MLResult GetFrameNumber(out ulong number)
{
MLResult.Code resultCode = NativeBindings.MLNativeSurfaceGetFrameNumber(Handle, out number);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLNativeSurfaceGetFrameNumber));
return MLResult.Create(resultCode);
}
private void OnFrameAvailable_CallbackThread()
{
OnFrameAvailable.Invoke();
}
}
}