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