Browse Source

[Android] Do not underutilize CPU/GPU when can't keep up with refresh rate (#18973)

pull/18993/head
Nikita Tsukanov 12 months ago
committed by GitHub
parent
commit
37121ba3be
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 38
      src/Android/Avalonia.Android/ChoreographerTimer.cs

38
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,8 +27,14 @@ 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;
@ -86,17 +93,32 @@ namespace Avalonia.Android
_choreographer.SetResult(Choreographer.Instance!);
Looper.Loop();
}
private void RenderLoop()
{
while (true)
{
_event.WaitOne();
long time;
lock (_lock)
{
time = _lastTime;
}
_tick?.Invoke(TimeSpan.FromTicks(time / 100));
}
}
public void DoFrame(long frameTimeNanos)
{
_tick?.Invoke(TimeSpan.FromTicks(frameTimeNanos / 100));
lock (_lock)
{
if (_count > 0 && _views.Count > 0)
{
Choreographer.Instance!.PostFrameCallback(this);
}
_lastTime = frameTimeNanos;
_event.Set();
}
}
}

Loading…
Cancel
Save