Browse Source

Dedicated render thread instead of relying on choreographer to drive timings

fixes/fix-android-perf-maybe-2
Nikita Tsukanov 10 months ago
parent
commit
0474932b5d
  1. 42
      src/Android/Avalonia.Android/ChoreographerTimer.cs

42
src/Android/Avalonia.Android/ChoreographerTimer.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Android.OS;
@ -7,16 +8,16 @@ using Android.Views;
using Avalonia.Reactive;
using Avalonia.Rendering;
using Java.Lang;
using ThreadPriority = System.Threading.ThreadPriority;
namespace Avalonia.Android
{
internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Choreographer.IFrameCallback
{
private readonly object _lock = new();
private readonly Thread _thread;
private AutoResetEvent _event = new(false);
private long _lastTime;
private readonly TaskCompletionSource<Choreographer> _choreographer = new();
private readonly ISet<AvaloniaView> _views = new HashSet<AvaloniaView>();
@ -26,10 +27,16 @@ namespace Avalonia.Android
public ChoreographerTimer()
{
_thread = new Thread(Loop);
_thread.Start();
new Thread(Loop)
{
Priority = ThreadPriority.AboveNormal
}.Start();
new Thread(RenderLoop)
{
Priority = ThreadPriority.AboveNormal
}.Start();
}
public bool RunsInBackground => true;
public event Action<TimeSpan> Tick
@ -82,10 +89,27 @@ namespace Avalonia.Android
private void Loop()
{
Console.WriteLine("Entering Chroreographer loop");
Looper.Prepare();
_choreographer.SetResult(Choreographer.Instance!);
Looper.Loop();
}
private void RenderLoop()
{
Console.WriteLine("Entering RenderThread loop");
while (true)
{
_event.WaitOne();
long time;
lock (_lock)
{
time = _lastTime;
}
_tick?.Invoke(TimeSpan.FromTicks(time / 100));
}
}
public void DoFrame(long frameTimeNanos)
{
@ -95,9 +119,9 @@ namespace Avalonia.Android
{
Choreographer.Instance!.PostFrameCallback(this);
}
_lastTime = frameTimeNanos;
_event.Set();
}
_tick?.Invoke(TimeSpan.FromTicks(frameTimeNanos / 100));
}
}
}

Loading…
Cancel
Save