From 90026c12d92b540aa55edc33ef468064523ccd56 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Tue, 15 Oct 2024 13:11:38 +0300 Subject: [PATCH 1/3] fix: X11's render timer interval was set to 1 frame per 16 ticks, not 16 ms (cherry picked from commit b77a2ef43accc28d839e62d2ff5bb822d2c2469b) --- src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs index 3a85977f166f..890e7828800e 100644 --- a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs +++ b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs @@ -93,7 +93,7 @@ public X11XamlRootHost(X11WindowWrapper wrapper, Window winUIWindow, XamlRoot xa _configureCallback = configureCallback; _renderTimer = new DispatcherTimer(); - _renderTimer.Interval = new TimeSpan(1000 / 16); + _renderTimer.Interval = TimeSpan.FromMilliseconds(16.66); // 60 hz _renderTimer.Tick += (sender, o) => { if (Interlocked.Exchange(ref _needsConfigureCallback, 0) == 1) @@ -103,8 +103,8 @@ public X11XamlRootHost(X11WindowWrapper wrapper, Window winUIWindow, XamlRoot xa if (_renderDirty) { - _renderer?.Render(); _renderDirty = false; + _renderer?.Render(); } }; _renderTimer.Start(); From 99c57ac7edaac8e3fb905ad204c9f6f2724458b1 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Tue, 15 Oct 2024 22:23:33 +0300 Subject: [PATCH 2/3] chore: make the target fps configurable (cherry picked from commit 36958071f32be4f66a1fbf003d1d7f1c6349c2a4) --- .../Builder/X11HostBuilder.cs | 13 ++++++++++++- src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs | 11 +++++++++-- src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs b/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs index 3bb2ed455bd2..e853861fee56 100644 --- a/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs +++ b/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs @@ -10,15 +10,26 @@ internal partial class X11HostBuilder : IPlatformHostBuilder [GeneratedRegex(@"^(?:(?[\w\.-]+))?:(?\d+)(?:\.(?\d+))?$")] private static partial Regex DisplayRegex(); + private int _targetFps = 60; + public X11HostBuilder() { } + /// + /// Sets the FPS that the application should try to achieve. + /// + public X11HostBuilder TargetFps(int targetFps) + { + _targetFps = targetFps; + return this; + } + public bool IsSupported => OperatingSystem.IsLinux() && Environment.GetEnvironmentVariable("DISPLAY") is { } displayString && DisplayRegex().Match(displayString).Success; public SkiaHost Create(Func appBuilder) - => new X11ApplicationHost(appBuilder); + => new X11ApplicationHost(appBuilder, _targetFps); } diff --git a/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs b/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs index f40b91496cd6..fa37b6fd8c73 100644 --- a/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs +++ b/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs @@ -23,6 +23,7 @@ namespace Uno.WinUI.Runtime.Skia.X11; public partial class X11ApplicationHost : SkiaHost, ISkiaApplicationHost, IDisposable { [ThreadStatic] private static bool _isDispatcherThread; + [ThreadStatic] private static int _targetFps; private readonly EventLoop _eventLoop; private readonly Func _appBuilder; @@ -70,18 +71,24 @@ static X11ApplicationHost() ApiExtensibility.Register(typeof(Uno.Graphics.INativeOpenGLWrapper), xamlRoot => new X11NativeOpenGLWrapper(xamlRoot)); } - public X11ApplicationHost(Func appBuilder) + public X11ApplicationHost(Func appBuilder, int targetFps = 60) { _appBuilder = appBuilder; _eventLoop = new EventLoop(); _eventLoop.Schedule(() => { Thread.CurrentThread.Name = "Uno Event Loop"; }, UI.Dispatching.NativeDispatcherPriority.Normal); - _eventLoop.Schedule(() => _isDispatcherThread = true, UI.Dispatching.NativeDispatcherPriority.Normal); + _eventLoop.Schedule(() => + { + _isDispatcherThread = true; + _targetFps = targetFps; + }, UI.Dispatching.NativeDispatcherPriority.Normal); CoreDispatcher.DispatchOverride = _eventLoop.Schedule; CoreDispatcher.HasThreadAccessOverride = () => _isDispatcherThread; } + internal static int TargetFps => _targetFps; + [LibraryImport("libc", StringMarshallingCustomType = typeof(AnsiStringMarshaller))] private static partial void setlocale(int type, string s); diff --git a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs index 890e7828800e..0f825a0b900e 100644 --- a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs +++ b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs @@ -93,7 +93,7 @@ public X11XamlRootHost(X11WindowWrapper wrapper, Window winUIWindow, XamlRoot xa _configureCallback = configureCallback; _renderTimer = new DispatcherTimer(); - _renderTimer.Interval = TimeSpan.FromMilliseconds(16.66); // 60 hz + _renderTimer.Interval = TimeSpan.FromSeconds(1.0 / X11ApplicationHost.TargetFps); // we're on the UI thread _renderTimer.Tick += (sender, o) => { if (Interlocked.Exchange(ref _needsConfigureCallback, 0) == 1) From 8b187667aa1274c91ca61c83ab4dc61be29a7f3e Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Wed, 16 Oct 2024 15:12:19 +0300 Subject: [PATCH 3/3] chore: renaming (cherry picked from commit 6475d1a4cde0c0111c91794ea8abdb0a748c8f60) --- src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs | 8 ++++---- src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs | 8 ++++---- src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs b/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs index e853861fee56..d667df3df6fa 100644 --- a/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs +++ b/src/Uno.UI.Runtime.Skia.X11/Builder/X11HostBuilder.cs @@ -10,7 +10,7 @@ internal partial class X11HostBuilder : IPlatformHostBuilder [GeneratedRegex(@"^(?:(?[\w\.-]+))?:(?\d+)(?:\.(?\d+))?$")] private static partial Regex DisplayRegex(); - private int _targetFps = 60; + private int _renderFrameRate = 60; public X11HostBuilder() { @@ -19,9 +19,9 @@ public X11HostBuilder() /// /// Sets the FPS that the application should try to achieve. /// - public X11HostBuilder TargetFps(int targetFps) + public X11HostBuilder RenderFrameRate(int renderFrameRate) { - _targetFps = targetFps; + _renderFrameRate = renderFrameRate; return this; } @@ -31,5 +31,5 @@ public bool IsSupported DisplayRegex().Match(displayString).Success; public SkiaHost Create(Func appBuilder) - => new X11ApplicationHost(appBuilder, _targetFps); + => new X11ApplicationHost(appBuilder, _renderFrameRate); } diff --git a/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs b/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs index fa37b6fd8c73..71376b4296f3 100644 --- a/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs +++ b/src/Uno.UI.Runtime.Skia.X11/X11ApplicationHost.cs @@ -23,7 +23,7 @@ namespace Uno.WinUI.Runtime.Skia.X11; public partial class X11ApplicationHost : SkiaHost, ISkiaApplicationHost, IDisposable { [ThreadStatic] private static bool _isDispatcherThread; - [ThreadStatic] private static int _targetFps; + [ThreadStatic] private static int _renderFrameRate; private readonly EventLoop _eventLoop; private readonly Func _appBuilder; @@ -71,7 +71,7 @@ static X11ApplicationHost() ApiExtensibility.Register(typeof(Uno.Graphics.INativeOpenGLWrapper), xamlRoot => new X11NativeOpenGLWrapper(xamlRoot)); } - public X11ApplicationHost(Func appBuilder, int targetFps = 60) + public X11ApplicationHost(Func appBuilder, int renderFrameRate = 60) { _appBuilder = appBuilder; @@ -81,13 +81,13 @@ public X11ApplicationHost(Func appBuilder, int targetFps = 60) _eventLoop.Schedule(() => { _isDispatcherThread = true; - _targetFps = targetFps; + _renderFrameRate = renderFrameRate; }, UI.Dispatching.NativeDispatcherPriority.Normal); CoreDispatcher.DispatchOverride = _eventLoop.Schedule; CoreDispatcher.HasThreadAccessOverride = () => _isDispatcherThread; } - internal static int TargetFps => _targetFps; + internal static int RenderFrameRate => _renderFrameRate; [LibraryImport("libc", StringMarshallingCustomType = typeof(AnsiStringMarshaller))] private static partial void setlocale(int type, string s); diff --git a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs index 0f825a0b900e..ebe654b459e1 100644 --- a/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs +++ b/src/Uno.UI.Runtime.Skia.X11/X11XamlRootHost.cs @@ -93,7 +93,7 @@ public X11XamlRootHost(X11WindowWrapper wrapper, Window winUIWindow, XamlRoot xa _configureCallback = configureCallback; _renderTimer = new DispatcherTimer(); - _renderTimer.Interval = TimeSpan.FromSeconds(1.0 / X11ApplicationHost.TargetFps); // we're on the UI thread + _renderTimer.Interval = TimeSpan.FromSeconds(1.0 / X11ApplicationHost.RenderFrameRate); // we're on the UI thread _renderTimer.Tick += (sender, o) => { if (Interlocked.Exchange(ref _needsConfigureCallback, 0) == 1)