From 267be8c1dfff92281aa805f0506bea8d505398ed Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Thu, 28 Mar 2024 13:28:54 +0100 Subject: [PATCH] feat: Use XamlRoot.RasterizationScale in GTK renderers --- .../Helpers/Dpi/DpiHelper.cs | 11 ++++++- .../Rendering/GLRenderSurfaceBase.cs | 21 ++++++------ .../Rendering/SoftwareRenderSurface.cs | 32 ++++++++++++------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.Gtk/Helpers/Dpi/DpiHelper.cs b/src/Uno.UI.Runtime.Skia.Gtk/Helpers/Dpi/DpiHelper.cs index 6c8ef9fad209..d7dc07f8afac 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/Helpers/Dpi/DpiHelper.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/Helpers/Dpi/DpiHelper.cs @@ -3,6 +3,7 @@ using Gtk; using Uno.Helpers; using Uno.UI.Runtime.Skia.Gtk.Helpers.Windows; +using Uno.UI.Runtime.Skia.Gtk.UI.Controls; using Windows.Graphics.Display; namespace Uno.UI.Runtime.Skia.Gtk.Helpers.Dpi; @@ -10,6 +11,7 @@ namespace Uno.UI.Runtime.Skia.Gtk.Helpers.Dpi; internal class DpiHelper { private readonly StartStopEventWrapper _dpiChangedWrapper; + private readonly UnoGtkWindow _window; private float? _dpi; @@ -18,6 +20,11 @@ public DpiHelper() _dpiChangedWrapper = new(StartDpiChanged, StopDpiChanged); } + public DpiHelper(UnoGtkWindow window) : this() + { + _window = window; + } + public event EventHandler DpiChanged { add => _dpiChangedWrapper.AddHandler(value); @@ -43,7 +50,7 @@ private void StopDpiChanged() GetWindow().Screen.SizeChanged -= OnScreenSizeChanged; } - private Window GetWindow() => GtkHost.Current.InitialWindow; + private Window GetWindow() => _window ?? GtkHost.Current.InitialWindow; private void OnWindowConfigure(object o, ConfigureEventArgs args) => CheckDpiUpdate(); @@ -83,4 +90,6 @@ internal float GetNativeDpi() } return dpi; } + + internal float RasterizationScale => (_dpi ?? GetNativeDpi()) / DisplayInformation.BaseDpi; } diff --git a/src/Uno.UI.Runtime.Skia.Gtk/Rendering/GLRenderSurfaceBase.cs b/src/Uno.UI.Runtime.Skia.Gtk/Rendering/GLRenderSurfaceBase.cs index 447cd6a1166d..dca8c1beb3f9 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/Rendering/GLRenderSurfaceBase.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/Rendering/GLRenderSurfaceBase.cs @@ -13,6 +13,7 @@ using Uno.UI.Hosting; using Microsoft.UI.Composition; using Uno.UI.Runtime.Skia.Gtk.Hosting; +using Microsoft.UI.Xaml; namespace Uno.UI.Runtime.Skia.Gtk { @@ -32,7 +33,6 @@ internal abstract partial class GLRenderSurfaceBase : GLArea, IGtkRenderer /// private const int GuardBand = 1; - private readonly DisplayInformation _displayInformation; private readonly IGtkXamlRootHost _host; private float? _scale = 1; @@ -47,14 +47,14 @@ internal abstract partial class GLRenderSurfaceBase : GLArea, IGtkRenderer /// In order to avoid virtual calls to and for performance reasons. /// protected bool _isGLES; + private readonly XamlRoot _xamlRoot; public SKColor BackgroundColor { get; set; } public GLRenderSurfaceBase(IGtkXamlRootHost host) { - var xamlRoot = GtkManager.XamlRootMap.GetRootForHost(host); - _displayInformation = WUX.XamlRoot.GetDisplayInformation(xamlRoot); - _displayInformation.DpiChanged += OnDpiChanged; + _xamlRoot = GtkManager.XamlRootMap.GetRootForHost(host) ?? throw new InvalidOperationException("XamlRoot must not be null when renderer is initialized"); + _xamlRoot.Changed += OnXamlRootChanged; UpdateDpi(); // Set some event handlers @@ -180,9 +180,6 @@ private void GLFlush() protected abstract GRContext TryBuildGRContext(); - private void OnDpiChanged(DisplayInformation sender, object args) => - UpdateDpi(); - public void TakeScreenshot(string filePath) { if (_surface != null) @@ -195,10 +192,16 @@ public void TakeScreenshot(string filePath) } } + private void OnXamlRootChanged(XamlRoot sender, XamlRootChangedEventArgs args) => UpdateDpi(); + private void UpdateDpi() { - _scale = (float)_displayInformation.RawPixelsPerViewPixel; - InvalidateRender(); + var newScale = (float)_xamlRoot.RasterizationScale; + if (_scale != newScale) + { + _scale = newScale; + InvalidateRender(); + } } } } diff --git a/src/Uno.UI.Runtime.Skia.Gtk/Rendering/SoftwareRenderSurface.cs b/src/Uno.UI.Runtime.Skia.Gtk/Rendering/SoftwareRenderSurface.cs index bd08496c324d..650165cd6e96 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/Rendering/SoftwareRenderSurface.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/Rendering/SoftwareRenderSurface.cs @@ -14,20 +14,21 @@ using Windows.Graphics.Display; using Microsoft.UI.Xaml; using Uno.UI.Runtime.Skia.Gtk.Hosting; +using Pango; +using Context = Cairo.Context; namespace Uno.UI.Runtime.Skia.Gtk; internal class SoftwareRenderSurface : DrawingArea, IGtkRenderer { - private readonly DisplayInformation _displayInformation; private SKSurface? _surface; private SKBitmap? _bitmap; private int _bheight, _bwidth; private ImageSurface? _gtkSurface; private int renderCount; - private float _dpi = 1; - + private float _scale = 1; + private XamlRoot _xamlRoot; private readonly SKColorType _colorType; private readonly IGtkXamlRootHost _host; @@ -36,9 +37,8 @@ internal class SoftwareRenderSurface : DrawingArea, IGtkRenderer public SoftwareRenderSurface(IGtkXamlRootHost host) { - var xamlRoot = GtkManager.XamlRootMap.GetRootForHost(host); - _displayInformation ??= XamlRoot.GetDisplayInformation(xamlRoot); - _displayInformation.DpiChanged += OnDpiChanged; + _xamlRoot = GtkManager.XamlRootMap.GetRootForHost(host) ?? throw new InvalidOperationException("XamlRoot must not be null when renderer is initialized"); + _xamlRoot.Changed += OnXamlRootChanged; UpdateDpi(); _colorType = SKImageInfo.PlatformColorType; @@ -57,8 +57,6 @@ public SoftwareRenderSurface(IGtkXamlRootHost host) public void InvalidateRender() => QueueDrawArea(0, 0, 10000, 10000); - private void OnDpiChanged(DisplayInformation sender, object args) => UpdateDpi(); - protected override bool OnDrawn(Context cr) { Stopwatch? sw = null; @@ -69,8 +67,8 @@ protected override bool OnDrawn(Context cr) this.Log().Trace($"Render {renderCount++}"); } - var scaledWidth = (int)(AllocatedWidth * _dpi); - var scaledHeight = (int)(AllocatedHeight * _dpi); + var scaledWidth = (int)(AllocatedWidth * _scale); + var scaledHeight = (int)(AllocatedHeight * _scale); // reset the surfaces (skia/cairo) and bitmap if the size has changed if (_surface == null || scaledWidth != _bwidth || scaledHeight != _bheight) @@ -93,7 +91,7 @@ protected override bool OnDrawn(Context cr) using (new SKAutoCanvasRestore(canvas, true)) { canvas.Clear(BackgroundColor); - canvas.Scale(_dpi); + canvas.Scale(_scale); if (_host.RootElement?.Visual is { } rootVisual) { @@ -130,5 +128,15 @@ public void TakeScreenshot(string filePath) _bitmap?.Encode(wstream, SKEncodedImageFormat.Png, 100); } - private float UpdateDpi() => _dpi = (float)_displayInformation.RawPixelsPerViewPixel; + private void OnXamlRootChanged(XamlRoot sender, XamlRootChangedEventArgs args) => UpdateDpi(); + + private void UpdateDpi() + { + var newScale = (float)_xamlRoot.RasterizationScale; + if (_scale != newScale) + { + _scale = newScale; + InvalidateRender(); + } + } }