using System; using System.Runtime.InteropServices; using Avalonia.Native.Interop; using Avalonia.Platform; namespace Avalonia.Native { internal unsafe class DeferredFramebuffer : ILockedFramebuffer { private readonly Func, bool> _lockWindow; public DeferredFramebuffer(Func, bool> lockWindow, int width, int height, Vector dpi) { _lockWindow = lockWindow; Address = Marshal.AllocHGlobal(width * height * 4); Size = new PixelSize(width, height); RowBytes = width * 4; Dpi = dpi; Format = PixelFormat.Bgra8888; } public IntPtr Address { get; set; } public PixelSize Size { get; set; } public int Height { get; set; } public int RowBytes { get; set; } public Vector Dpi { get; set; } public PixelFormat Format { get; set; } class Disposer : CallbackBase { private IntPtr _ptr; public Disposer(IntPtr ptr) { _ptr = ptr; } protected override void Destroyed() { if(_ptr != IntPtr.Zero) { Marshal.FreeHGlobal(_ptr); _ptr = IntPtr.Zero; } } } public void Dispose() { if (Address == IntPtr.Zero) return; if (!_lockWindow(win => { var fb = new AvnFramebuffer { Data = Address.ToPointer(), Dpi = new AvnVector { X = Dpi.X, Y = Dpi.Y }, Width = Size.Width, Height = Size.Height, PixelFormat = (AvnPixelFormat)Format, Stride = RowBytes }; using (var d = new Disposer(Address)) { win.ThreadSafeSetSwRenderedFrame(&fb, d); } })) { Marshal.FreeHGlobal(Address); } Address = IntPtr.Zero; } } }