Skip to content

Commit ae376d9

Browse files
committed
[Android] Do not underutilize CPU/GPU when can't keep up with refresh rate
1 parent 337f004 commit ae376d9

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

src/Android/Avalonia.Android/ChoreographerTimer.cs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Threading;
34
using System.Threading.Tasks;
45

56
using Android.OS;
67
using Android.Views;
78

89
using Avalonia.Reactive;
910
using Avalonia.Rendering;
10-
11-
using Java.Lang;
11+
using ThreadPriority = System.Threading.ThreadPriority;
1212

1313
namespace Avalonia.Android
1414
{
1515
internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Choreographer.IFrameCallback
1616
{
1717
private readonly object _lock = new();
18-
19-
private readonly Thread _thread;
18+
19+
private AutoResetEvent _event = new(false);
20+
private long _lastTime;
2021
private readonly TaskCompletionSource<Choreographer> _choreographer = new();
2122

2223
private readonly ISet<AvaloniaView> _views = new HashSet<AvaloniaView>();
@@ -26,8 +27,14 @@ internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Chore
2627

2728
public ChoreographerTimer()
2829
{
29-
_thread = new Thread(Loop);
30-
_thread.Start();
30+
new Thread(Loop)
31+
{
32+
Priority = ThreadPriority.AboveNormal
33+
}.Start();
34+
new Thread(RenderLoop)
35+
{
36+
Priority = ThreadPriority.AboveNormal
37+
}.Start();
3138
}
3239

3340
public bool RunsInBackground => true;
@@ -86,17 +93,32 @@ private void Loop()
8693
_choreographer.SetResult(Choreographer.Instance!);
8794
Looper.Loop();
8895
}
96+
97+
private void RenderLoop()
98+
{
99+
while (true)
100+
{
101+
_event.WaitOne();
102+
long time;
103+
lock (_lock)
104+
{
105+
time = _lastTime;
106+
}
107+
_tick?.Invoke(TimeSpan.FromTicks(time / 100));
108+
}
109+
}
110+
89111

90112
public void DoFrame(long frameTimeNanos)
91113
{
92-
_tick?.Invoke(TimeSpan.FromTicks(frameTimeNanos / 100));
93-
94114
lock (_lock)
95115
{
96116
if (_count > 0 && _views.Count > 0)
97117
{
98118
Choreographer.Instance!.PostFrameCallback(this);
99119
}
120+
_lastTime = frameTimeNanos;
121+
_event.Set();
100122
}
101123
}
102124
}

0 commit comments

Comments
 (0)