Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/Skia/Avalonia.Skia/Gpu/Metal/AutoReleasePool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace Avalonia.Skia.Metal;

internal sealed partial class AutoReleasePool : IDisposable
{
private IntPtr _pool;

public AutoReleasePool()
{
_pool = Push();
}

public void Dispose()
{
var pool = Interlocked.Exchange(ref _pool, IntPtr.Zero);
if (pool != IntPtr.Zero)
{
Pop(pool);
}
}

[LibraryImport("libobjc", EntryPoint = "objc_autoreleasePoolPush")]
private static partial IntPtr Push();

[LibraryImport("libobjc", EntryPoint = "objc_autoreleasePoolPop")]
private static partial void Pop(IntPtr pool);
}
36 changes: 29 additions & 7 deletions src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,33 @@ public void Dispose()
public ISkiaGpuRenderSession BeginRenderingSession(IRenderTarget.RenderTargetSceneInfo sceneInfo)
{
// TODO: use expectedPixelSize
var session = (_target ?? throw new ObjectDisposedException(nameof(SkiaMetalRenderTarget))).BeginRendering();
var backendTarget = new GRBackendRenderTarget(session.Size.Width, session.Size.Height,
new GRMtlTextureInfo(session.Texture));
IMetalPlatformSurfaceRenderingSession? session = null;
GRBackendRenderTarget? backendTarget = null;
SKSurface? surface = null;
var success = false;
try
{
session = (_target ?? throw new ObjectDisposedException(nameof(SkiaMetalRenderTarget))).BeginRendering();
backendTarget = new GRBackendRenderTarget(session.Size.Width, session.Size.Height,
new GRMtlTextureInfo(session.Texture));

var surface = SKSurface.Create(_gpu._context!, backendTarget,
session.IsYFlipped ? GRSurfaceOrigin.BottomLeft : GRSurfaceOrigin.TopLeft,
SKColorType.Bgra8888);
surface = SKSurface.Create(_gpu._context!, backendTarget,
session.IsYFlipped ? GRSurfaceOrigin.BottomLeft : GRSurfaceOrigin.TopLeft,
SKColorType.Bgra8888);

return new SkiaMetalRenderSession(_gpu, surface, session, backendTarget);
var result = new SkiaMetalRenderSession(_gpu, surface, session, backendTarget);
success = true;
return result;
}
finally
{
if (!success)
{
surface?.Dispose();
backendTarget?.Dispose();
session?.Dispose();
}
}
}

public PlatformRenderTargetState State => _target?.State ?? PlatformRenderTargetState.Disposed;
Expand All @@ -117,12 +135,14 @@ internal class SkiaMetalRenderSession : ISkiaGpuRenderSession
private SKSurface? _surface;
private IMetalPlatformSurfaceRenderingSession? _session;
private GRBackendRenderTarget? _backendTarget;
private readonly AutoReleasePool _autoReleasePool;

public SkiaMetalRenderSession(SkiaMetalGpu gpu,
SKSurface surface,
IMetalPlatformSurfaceRenderingSession session,
GRBackendRenderTarget backendTarget)
{
_autoReleasePool = new AutoReleasePool();
_gpu = gpu;
_surface = surface;
_session = session;
Expand All @@ -141,6 +161,8 @@ public void Dispose()
_session = null;
_backendTarget?.Dispose();
_backendTarget = null;

_autoReleasePool.Dispose();
}

public GRContext GrContext => _gpu._context!;
Expand Down