100 lines
2.6 KiB
C#
100 lines
2.6 KiB
C#
using UnityEngine;
|
|
using System.Runtime.InteropServices;
|
|
using IntPtr = System.IntPtr;
|
|
|
|
namespace Klak.Spout {
|
|
|
|
//
|
|
// Wrapper class for receiver instances on the native plugin side
|
|
//
|
|
sealed class Receiver : System.IDisposable
|
|
{
|
|
#region Public property
|
|
|
|
public Texture2D Texture => _texture;
|
|
|
|
#endregion
|
|
|
|
#region Private objects
|
|
|
|
IntPtr _plugin;
|
|
EventKicker _event;
|
|
Texture2D _texture;
|
|
|
|
#endregion
|
|
|
|
#region Object lifecycle
|
|
|
|
public Receiver(string sourceName)
|
|
{
|
|
if (string.IsNullOrEmpty(sourceName)) return;
|
|
|
|
// Plugin object allocation
|
|
_plugin = Plugin.CreateReceiver(sourceName);
|
|
if (_plugin == IntPtr.Zero) return;
|
|
|
|
// Event kicker (heap block for interop communication)
|
|
_event = new EventKicker(new EventData(_plugin));
|
|
|
|
// Initial update event
|
|
_event.IssuePluginEvent(EventID.UpdateReceiver);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_plugin != IntPtr.Zero)
|
|
{
|
|
// Isssue the closer event to destroy the plugin object from the
|
|
// render thread.
|
|
_event.IssuePluginEvent(EventID.CloseReceiver);
|
|
|
|
// Event kicker (interop memory) deallocation:
|
|
// The close event above will refer to the block from the render
|
|
// thread, so we actually can't free the memory here. To avoid this
|
|
// problem, EventKicker uses MemoryPool to delay the memory
|
|
// deallocation by the end of the frame.
|
|
_event.Dispose();
|
|
|
|
_plugin = IntPtr.Zero;
|
|
}
|
|
|
|
Utility.Destroy(_texture);
|
|
_texture = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Frame update method
|
|
|
|
public void Update()
|
|
{
|
|
if (_plugin == IntPtr.Zero) return;
|
|
|
|
var data = Plugin.GetReceiverData(_plugin);
|
|
|
|
// Texture refresh:
|
|
// If we are referring to an old texture pointer, destroy it first.
|
|
if (_texture != null &&
|
|
_texture.GetNativeTexturePtr() != data.texturePointer)
|
|
{
|
|
Utility.Destroy(_texture);
|
|
_texture = null;
|
|
}
|
|
|
|
// Lazy initialization:
|
|
// We try creating a receiver texture every frame until getting a
|
|
// correct one.
|
|
if (_texture == null && data.texturePointer != IntPtr.Zero)
|
|
_texture = Texture2D.CreateExternalTexture
|
|
((int)data.width, (int)data.height, TextureFormat.BGRA32,
|
|
false, true, data.texturePointer);
|
|
|
|
// Update event for the render thread
|
|
_event.IssuePluginEvent(EventID.UpdateReceiver);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
} // namespace Klak.Spout
|