source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.WinUI/SKSwapChainPanel.macOS.cs (77 lines of code) (raw):
using CoreVideo;
#if WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#endif
#if WINDOWS || WINUI
namespace SkiaSharp.Views.Windows
#else
namespace SkiaSharp.Views.UWP
#endif
{
public partial class SKSwapChainPanel : FrameworkElement
{
private SKGLView glView;
private CVDisplayLink displayLink;
public SKSwapChainPanel()
{
Initialize();
}
private SKSize GetCanvasSize() =>
glView?.CanvasSize ?? SKSize.Empty;
private GRContext GetGRContext() =>
glView?.GRContext;
partial void DoLoaded()
{
glView = new SKGLView(Bounds);
glView.PaintSurface += OnPaintSurface;
AddSubview(glView);
}
partial void DoUnloaded()
{
DoEnableRenderLoop(false);
if (glView != null)
{
glView.RemoveFromSuperview();
glView.PaintSurface -= OnPaintSurface;
glView.Dispose();
glView = null;
}
}
private void DoInvalidate() =>
DoEnableRenderLoop(true);
private void OnPaintSurface(object sender, SKPaintGLSurfaceEventArgs e) =>
OnPaintSurface(e);
partial void DoEnableRenderLoop(bool enable)
{
// stop the render loop
if (!enable)
{
if (displayLink != null)
{
displayLink.Stop();
displayLink.Dispose();
displayLink = null;
}
return;
}
// only start if we haven't already
if (displayLink != null)
return;
// create the loop
displayLink = new CVDisplayLink();
displayLink.SetOutputCallback(delegate
{
// redraw the view
glView?.BeginInvokeOnMainThread(() =>
{
if (glView != null)
glView.NeedsDisplay = true;
});
// stop the render loop if it has been disabled or the views are disposed
if (glView == null || !EnableRenderLoop)
DoEnableRenderLoop(false);
return CVReturn.Success;
});
displayLink.Start();
}
}
}