committed by
GitHub
6 changed files with 316 additions and 33 deletions
@ -0,0 +1,77 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using Avalonia.Native.Interop; |
|||
using Avalonia.Platform; |
|||
using SharpGen.Runtime; |
|||
|
|||
namespace Avalonia.Native |
|||
{ |
|||
public class DeferredFramebuffer : ILockedFramebuffer |
|||
{ |
|||
private readonly Func<Action<IAvnWindowBase>, bool> _lockWindow; |
|||
public DeferredFramebuffer(Func<Action<IAvnWindowBase>, bool> lockWindow, |
|||
int width, int height, Vector dpi) |
|||
{ |
|||
_lockWindow = lockWindow; |
|||
Address = Marshal.AllocHGlobal(width * height * 4); |
|||
Width = width; |
|||
Height = height; |
|||
RowBytes = width * 4; |
|||
Dpi = dpi; |
|||
Format = PixelFormat.Rgba8888; |
|||
} |
|||
|
|||
public IntPtr Address { get; set; } |
|||
public int Width { 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, |
|||
Dpi = new AvnVector |
|||
{ |
|||
X = Dpi.X, |
|||
Y = Dpi.Y |
|||
}, |
|||
Width = Width, |
|||
Height = Height, |
|||
PixelFormat = (AvnPixelFormat)Format, |
|||
Stride = RowBytes |
|||
}; |
|||
using (var d = new Disposer(Address)) |
|||
win.ThreadSafeSetSwRenderedFrame(ref fb, d); |
|||
})) |
|||
Marshal.FreeHGlobal(Address); |
|||
Address = IntPtr.Zero; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Rendering; |
|||
using Avalonia.VisualTree; |
|||
|
|||
namespace Avalonia.Native |
|||
{ |
|||
public class DeferredRendererProxy : IRenderer, IRenderLoopTask, IRenderLoop |
|||
{ |
|||
object _lock = new object(); |
|||
void IRenderLoop.Add(IRenderLoopTask i) |
|||
{ |
|||
AvaloniaLocator.Current.GetService<IRenderLoop>().Add(this); |
|||
} |
|||
|
|||
void IRenderLoop.Remove(IRenderLoopTask i) |
|||
{ |
|||
AvaloniaLocator.Current.GetService<IRenderLoop>().Remove(this); |
|||
} |
|||
|
|||
|
|||
DeferredRenderer _renderer; |
|||
IRenderLoopTask _rendererTask; |
|||
public DeferredRendererProxy(IRenderRoot root) |
|||
{ |
|||
_renderer = new DeferredRenderer(root, this); |
|||
_rendererTask = (IRenderLoopTask)_renderer; |
|||
} |
|||
|
|||
public bool DrawFps{ |
|||
get => _renderer.DrawFps; |
|||
set => _renderer.DrawFps = value; |
|||
} |
|||
public bool DrawDirtyRects |
|||
{ |
|||
get => _renderer.DrawDirtyRects; |
|||
set => _renderer.DrawDirtyRects = value; |
|||
} |
|||
|
|||
public bool NeedsUpdate => _rendererTask.NeedsUpdate; |
|||
|
|||
public void AddDirty(IVisual visual) => _renderer.AddDirty(visual); |
|||
|
|||
public void Dispose() => _renderer.Dispose(); |
|||
|
|||
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter) |
|||
{ |
|||
return _renderer.HitTest(p, root, filter); |
|||
} |
|||
|
|||
public void Paint(Rect rect) |
|||
{ |
|||
if (NeedsUpdate) |
|||
Update(TimeSpan.FromMilliseconds(Environment.TickCount)); |
|||
Render(); |
|||
} |
|||
|
|||
public void Resized(Size size) => _renderer.Resized(size); |
|||
|
|||
public void Start() => _renderer.Start(); |
|||
|
|||
public void Stop() => _renderer.Stop(); |
|||
|
|||
public void Update(TimeSpan time) |
|||
{ |
|||
_rendererTask.Update(time); |
|||
} |
|||
|
|||
public void Render() |
|||
{ |
|||
lock(_lock) |
|||
{ |
|||
_rendererTask.Render(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue