Skip to content

Commit f3f26eb

Browse files
authored
Introduced a way to lease the underlying platform graphics context from Skia context (#14652)
* Introduced a way to lease the underlying platform graphics context from Skia context * API suppression
1 parent 1e078c4 commit f3f26eb

File tree

6 files changed

+82
-6
lines changed

6 files changed

+82
-6
lines changed

api/Avalonia.Skia.nupkg.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
3+
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
4+
<Suppression>
5+
<DiagnosticId>CP0006</DiagnosticId>
6+
<Target>M:Avalonia.Skia.ISkiaSharpApiLease.TryLeasePlatformGraphicsApi</Target>
7+
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
8+
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
9+
</Suppression>
10+
</Suppressions>

src/Skia/Avalonia.Skia/DrawingContextImpl.cs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ private class ApiLease : ISkiaSharpApiLease
9999
private readonly DrawingContextImpl _context;
100100
private readonly SKMatrix _revertTransform;
101101
private bool _isDisposed;
102+
private bool _leased;
102103

103104
public ApiLease(DrawingContextImpl context)
104105
{
@@ -107,11 +108,26 @@ public ApiLease(DrawingContextImpl context)
107108
_context._leased = true;
108109
}
109110

110-
public SKCanvas SkCanvas => _context.Canvas;
111+
void CheckLease()
112+
{
113+
if (_leased)
114+
throw new InvalidOperationException("The underlying graphics API is currently leased");
115+
}
116+
117+
T CheckLease<T>(T rv)
118+
{
119+
CheckLease();
120+
return rv;
121+
}
122+
123+
public SKCanvas SkCanvas => CheckLease(_context.Canvas);
124+
// GrContext is accessible during the lease since one might want to wrap native resources
125+
// Into Skia ones
111126
public GRContext? GrContext => _context.GrContext;
112-
public SKSurface? SkSurface => _context.Surface;
113-
public double CurrentOpacity => _context._currentOpacity;
114-
127+
public SKSurface? SkSurface => CheckLease(_context.Surface);
128+
public double CurrentOpacity => CheckLease(_context._currentOpacity);
129+
130+
115131
public void Dispose()
116132
{
117133
if (!_isDisposed)
@@ -121,6 +137,36 @@ public void Dispose()
121137
_isDisposed = true;
122138
}
123139
}
140+
141+
class PlatformApiLease : ISkiaSharpPlatformGraphicsApiLease
142+
{
143+
private readonly ApiLease _parent;
144+
145+
public PlatformApiLease(ApiLease parent, IPlatformGraphicsContext context)
146+
{
147+
_parent = parent;
148+
_parent.GrContext?.Flush();
149+
Context = context;
150+
_parent._leased = true;
151+
}
152+
153+
public void Dispose()
154+
{
155+
_parent._leased = false;
156+
_parent.GrContext?.ResetContext();
157+
}
158+
159+
public IPlatformGraphicsContext Context { get; }
160+
}
161+
162+
public ISkiaSharpPlatformGraphicsApiLease? TryLeasePlatformGraphicsApi()
163+
{
164+
CheckLease();
165+
if (_context._gpu is ISkiaGpuWithPlatformGraphicsContext gpu &&
166+
gpu.PlatformGraphicsContext is { } context)
167+
return new PlatformApiLease(this, context);
168+
return null;
169+
}
124170
}
125171
}
126172

src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using Avalonia.Metadata;
34
using Avalonia.Platform;
45
using SkiaSharp;
56

@@ -24,6 +25,13 @@ public interface ISkiaGpu : IPlatformGraphicsContext
2425
/// <param name="session">An optional custom render session.</param>
2526
ISkiaSurface? TryCreateSurface(PixelSize size, ISkiaGpuRenderSession? session);
2627
}
28+
29+
//TODO12: Merge into ISkiaGpu
30+
[Unstable]
31+
public interface ISkiaGpuWithPlatformGraphicsContext : ISkiaGpu
32+
{
33+
IPlatformGraphicsContext? PlatformGraphicsContext { get; }
34+
}
2735

2836
public interface ISkiaSurface : IDisposable
2937
{

src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
using System.Collections.Generic;
33
using System.Runtime.InteropServices;
44
using Avalonia.Metal;
5+
using Avalonia.Platform;
56
using SkiaSharp;
67

78
namespace Avalonia.Skia.Metal;
89

9-
internal class SkiaMetalGpu : ISkiaGpu
10+
internal class SkiaMetalGpu : ISkiaGpu, ISkiaGpuWithPlatformGraphicsContext
1011
{
1112
private SkiaMetalApi _api = new();
1213
private GRContext? _context;
@@ -31,6 +32,7 @@ public void Dispose()
3132

3233
public bool IsLost => false;
3334
public IDisposable EnsureCurrent() => _device.EnsureCurrent();
35+
public IPlatformGraphicsContext? PlatformGraphicsContext => _device;
3436

3537
public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable<object> surfaces)
3638
{

src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
namespace Avalonia.Skia
1212
{
13-
internal class GlSkiaGpu : ISkiaGpu, IOpenGlTextureSharingRenderInterfaceContextFeature
13+
internal class GlSkiaGpu : ISkiaGpu, IOpenGlTextureSharingRenderInterfaceContextFeature,
14+
ISkiaGpuWithPlatformGraphicsContext
1415
{
1516
private readonly GRContext _grContext;
1617
private readonly IGlContext _glContext;
@@ -152,6 +153,7 @@ public void Dispose()
152153

153154
public bool IsLost => _glContext.IsLost;
154155
public IDisposable EnsureCurrent() => _glContext.EnsureCurrent();
156+
public IPlatformGraphicsContext? PlatformGraphicsContext => _glContext;
155157

156158
public object? TryGetFeature(Type featureType)
157159
{

src/Skia/Avalonia.Skia/ISkiaSharpApiLeaseFeature.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using Avalonia.Metadata;
3+
using Avalonia.Platform;
34
using SkiaSharp;
45

56
namespace Avalonia.Skia;
@@ -17,4 +18,11 @@ public interface ISkiaSharpApiLease : IDisposable
1718
GRContext? GrContext { get; }
1819
SKSurface? SkSurface { get; }
1920
double CurrentOpacity { get; }
21+
ISkiaSharpPlatformGraphicsApiLease? TryLeasePlatformGraphicsApi();
22+
}
23+
24+
[Unstable]
25+
public interface ISkiaSharpPlatformGraphicsApiLease : IDisposable
26+
{
27+
IPlatformGraphicsContext Context { get; }
2028
}

0 commit comments

Comments
 (0)