Browse Source

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
pull/14664/head
Nikita Tsukanov 2 years ago
committed by GitHub
parent
commit
f3f26eb113
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      api/Avalonia.Skia.nupkg.xml
  2. 54
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  3. 8
      src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs
  4. 4
      src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
  5. 4
      src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs
  6. 8
      src/Skia/Avalonia.Skia/ISkiaSharpApiLeaseFeature.cs

10
api/Avalonia.Skia.nupkg.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaSharpApiLease.TryLeasePlatformGraphicsApi</Target>
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
</Suppression>
</Suppressions>

54
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -99,6 +99,7 @@ namespace Avalonia.Skia
private readonly DrawingContextImpl _context; private readonly DrawingContextImpl _context;
private readonly SKMatrix _revertTransform; private readonly SKMatrix _revertTransform;
private bool _isDisposed; private bool _isDisposed;
private bool _leased;
public ApiLease(DrawingContextImpl context) public ApiLease(DrawingContextImpl context)
{ {
@ -107,11 +108,26 @@ namespace Avalonia.Skia
_context._leased = true; _context._leased = true;
} }
public SKCanvas SkCanvas => _context.Canvas; void CheckLease()
{
if (_leased)
throw new InvalidOperationException("The underlying graphics API is currently leased");
}
T CheckLease<T>(T rv)
{
CheckLease();
return rv;
}
public SKCanvas SkCanvas => CheckLease(_context.Canvas);
// GrContext is accessible during the lease since one might want to wrap native resources
// Into Skia ones
public GRContext? GrContext => _context.GrContext; public GRContext? GrContext => _context.GrContext;
public SKSurface? SkSurface => _context.Surface; public SKSurface? SkSurface => CheckLease(_context.Surface);
public double CurrentOpacity => _context._currentOpacity; public double CurrentOpacity => CheckLease(_context._currentOpacity);
public void Dispose() public void Dispose()
{ {
if (!_isDisposed) if (!_isDisposed)
@ -121,6 +137,36 @@ namespace Avalonia.Skia
_isDisposed = true; _isDisposed = true;
} }
} }
class PlatformApiLease : ISkiaSharpPlatformGraphicsApiLease
{
private readonly ApiLease _parent;
public PlatformApiLease(ApiLease parent, IPlatformGraphicsContext context)
{
_parent = parent;
_parent.GrContext?.Flush();
Context = context;
_parent._leased = true;
}
public void Dispose()
{
_parent._leased = false;
_parent.GrContext?.ResetContext();
}
public IPlatformGraphicsContext Context { get; }
}
public ISkiaSharpPlatformGraphicsApiLease? TryLeasePlatformGraphicsApi()
{
CheckLease();
if (_context._gpu is ISkiaGpuWithPlatformGraphicsContext gpu &&
gpu.PlatformGraphicsContext is { } context)
return new PlatformApiLease(this, context);
return null;
}
} }
} }

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

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Metadata;
using Avalonia.Platform; using Avalonia.Platform;
using SkiaSharp; using SkiaSharp;
@ -24,6 +25,13 @@ namespace Avalonia.Skia
/// <param name="session">An optional custom render session.</param> /// <param name="session">An optional custom render session.</param>
ISkiaSurface? TryCreateSurface(PixelSize size, ISkiaGpuRenderSession? session); ISkiaSurface? TryCreateSurface(PixelSize size, ISkiaGpuRenderSession? session);
} }
//TODO12: Merge into ISkiaGpu
[Unstable]
public interface ISkiaGpuWithPlatformGraphicsContext : ISkiaGpu
{
IPlatformGraphicsContext? PlatformGraphicsContext { get; }
}
public interface ISkiaSurface : IDisposable public interface ISkiaSurface : IDisposable
{ {

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

@ -2,11 +2,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Metal; using Avalonia.Metal;
using Avalonia.Platform;
using SkiaSharp; using SkiaSharp;
namespace Avalonia.Skia.Metal; namespace Avalonia.Skia.Metal;
internal class SkiaMetalGpu : ISkiaGpu internal class SkiaMetalGpu : ISkiaGpu, ISkiaGpuWithPlatformGraphicsContext
{ {
private SkiaMetalApi _api = new(); private SkiaMetalApi _api = new();
private GRContext? _context; private GRContext? _context;
@ -31,6 +32,7 @@ internal class SkiaMetalGpu : ISkiaGpu
public bool IsLost => false; public bool IsLost => false;
public IDisposable EnsureCurrent() => _device.EnsureCurrent(); public IDisposable EnsureCurrent() => _device.EnsureCurrent();
public IPlatformGraphicsContext? PlatformGraphicsContext => _device;
public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable<object> surfaces) public ISkiaGpuRenderTarget? TryCreateRenderTarget(IEnumerable<object> surfaces)
{ {

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

@ -10,7 +10,8 @@ using static Avalonia.OpenGL.GlConsts;
namespace Avalonia.Skia namespace Avalonia.Skia
{ {
internal class GlSkiaGpu : ISkiaGpu, IOpenGlTextureSharingRenderInterfaceContextFeature internal class GlSkiaGpu : ISkiaGpu, IOpenGlTextureSharingRenderInterfaceContextFeature,
ISkiaGpuWithPlatformGraphicsContext
{ {
private readonly GRContext _grContext; private readonly GRContext _grContext;
private readonly IGlContext _glContext; private readonly IGlContext _glContext;
@ -152,6 +153,7 @@ namespace Avalonia.Skia
public bool IsLost => _glContext.IsLost; public bool IsLost => _glContext.IsLost;
public IDisposable EnsureCurrent() => _glContext.EnsureCurrent(); public IDisposable EnsureCurrent() => _glContext.EnsureCurrent();
public IPlatformGraphicsContext? PlatformGraphicsContext => _glContext;
public object? TryGetFeature(Type featureType) public object? TryGetFeature(Type featureType)
{ {

8
src/Skia/Avalonia.Skia/ISkiaSharpApiLeaseFeature.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Platform;
using SkiaSharp; using SkiaSharp;
namespace Avalonia.Skia; namespace Avalonia.Skia;
@ -17,4 +18,11 @@ public interface ISkiaSharpApiLease : IDisposable
GRContext? GrContext { get; } GRContext? GrContext { get; }
SKSurface? SkSurface { get; } SKSurface? SkSurface { get; }
double CurrentOpacity { get; } double CurrentOpacity { get; }
ISkiaSharpPlatformGraphicsApiLease? TryLeasePlatformGraphicsApi();
}
[Unstable]
public interface ISkiaSharpPlatformGraphicsApiLease : IDisposable
{
IPlatformGraphicsContext Context { get; }
} }

Loading…
Cancel
Save