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