Skip to content

Commit 17deaa4

Browse files
MartinZikmundmergify[bot]
authored andcommitted
feat: Use shared SKPicture recording on WASM
(cherry picked from commit c03a12d)
1 parent 5e53694 commit 17deaa4

File tree

1 file changed

+41
-25
lines changed

1 file changed

+41
-25
lines changed

src/Uno.UI.Runtime.Skia.WebAssembly.Browser/Rendering/BrowserRenderer.cs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
using SkiaSharp;
2-
using MUX = Microsoft.UI.Xaml;
3-
using Uno.Foundation.Logging;
4-
using Windows.Graphics.Display;
1+
using System.Diagnostics;
52
using System.Runtime.InteropServices.JavaScript;
6-
using Uno.UI.Hosting;
7-
using System.Diagnostics;
8-
using Uno.UI.Helpers;
3+
using System.Threading;
94
using Microsoft.UI.Xaml.Media;
5+
using SkiaSharp;
6+
using Uno.Foundation.Logging;
107
using Uno.UI.Dispatching;
8+
using Uno.UI.Helpers;
9+
using Uno.UI.Hosting;
10+
using Windows.Graphics.Display;
1111

1212
namespace Uno.UI.Runtime.Skia;
1313

@@ -33,6 +33,8 @@ internal partial class BrowserRenderer
3333
private GRBackendRenderTarget? _renderTarget;
3434
private SKSurface? _surface;
3535
private SKCanvas? _canvas;
36+
private SKPicture? _picture;
37+
private SKPath? _clipPath;
3638

3739
private SKSizeI? _lastSize;
3840

@@ -60,18 +62,32 @@ private void Initialize()
6062
_jsInfo = NativeMethods.CreateContext(this, _nativeSwapChainPanel, WebAssemblyWindowWrapper.Instance?.CanvasId ?? "invalid");
6163
}
6264

63-
internal void InvalidateRender() => NativeMethods.Invalidate(_nativeSwapChainPanel);
64-
65-
private void RenderFrame()
65+
internal void InvalidateRender()
6666
{
67-
using var _ = _fpsHelper.BeginFrame();
68-
69-
if (_host.RootElement is { } rootElement && (rootElement.IsArrangeDirtyOrArrangeDirtyPath || rootElement.IsMeasureDirtyOrMeasureDirtyPath))
67+
if (_host.RootElement is not { } rootElement || (rootElement.IsArrangeDirtyOrArrangeDirtyPath || rootElement.IsMeasureDirtyOrMeasureDirtyPath))
7068
{
71-
InvalidateRender();
69+
// Try again next tick
70+
NativeDispatcher.Main.Enqueue(() => ((IXamlRootHost)this).InvalidateRender());
7271
return;
7372
}
7473

74+
var (picture, path) = SkiaRenderHelper.RecordPictureAndReturnPath(
75+
(int)(Microsoft.UI.Xaml.Window.CurrentSafe!.Bounds.Width),
76+
(int)(Microsoft.UI.Xaml.Window.CurrentSafe!.Bounds.Height),
77+
rootElement.Visual,
78+
invertPath: false);
79+
_host.RootElement?.XamlRoot?.InvokeFramePainted();
80+
81+
Interlocked.Exchange(ref _picture, picture);
82+
Interlocked.Exchange(ref _clipPath, path);
83+
84+
NativeMethods.Invalidate(_nativeSwapChainPanel);
85+
}
86+
87+
private void RenderFrame()
88+
{
89+
using var _ = _fpsHelper.BeginFrame();
90+
7591
if (!_jsInfo.IsValid)
7692
{
7793
Initialize();
@@ -134,21 +150,21 @@ private void RenderFrame()
134150
}
135151
}
136152

153+
var currentPicture = _picture;
154+
var currentClipPath = _clipPath;
155+
137156
using (new SKAutoCanvasRestore(_canvas, true))
138157
{
139158
_surface.Canvas.Clear(SKColors.Transparent);
140159
_surface.Canvas.Scale((float)scale);
141-
if (_host.RootElement?.Visual is { } rootVisual)
142-
{
143-
var negativePath = SkiaRenderHelper.RenderRootVisualAndReturnNegativePath(_renderTarget.Width, _renderTarget.Height, rootVisual, _canvas);
144-
_fpsHelper.DrawFps(_canvas);
145-
// Unlike other skia platforms, on skia/wasm we need to undo the scaling adjustment that happens inside
146-
// RenderRootVisualAndReturnNegativePath since the numbers we get from native are already scaled, so we
147-
// don't need to do our own scaling in RenderRootVisualAndReturnNegativePath.
148-
negativePath.Transform(SKMatrix.CreateScale((float)(1 / scale), (float)(1 / scale)), negativePath);
149-
BrowserNativeElementHostingExtension.SetSvgClipPathForNativeElementHost(!negativePath.IsEmpty ? negativePath.ToSvgPathData() : "");
150-
_host.RootElement?.XamlRoot?.InvokeFramePainted();
151-
}
160+
_surface.Canvas.DrawPicture(currentPicture);
161+
_fpsHelper.DrawFps(_canvas);
162+
163+
// Unlike other skia platforms, on skia/wasm we need to undo the scaling adjustment that happens inside
164+
// RenderRootVisualAndReturnNegativePath since the numbers we get from native are already scaled, so we
165+
// don't need to do our own scaling in RenderRootVisualAndReturnNegativePath.
166+
currentClipPath?.Transform(SKMatrix.CreateScale((float)(1 / scale), (float)(1 / scale)), currentClipPath);
167+
BrowserNativeElementHostingExtension.SetSvgClipPathForNativeElementHost(currentClipPath is not null && !currentClipPath.IsEmpty ? currentClipPath.ToSvgPathData() : "");
152168
}
153169

154170
// update the control

0 commit comments

Comments
 (0)