csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
5.3 KiB
150 lines
5.3 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using Avalonia.Platform;
|
|
|
|
namespace Avalonia.Rendering.Composition;
|
|
|
|
internal class CompositionInterop : ICompositionGpuInterop
|
|
{
|
|
private readonly Compositor _compositor;
|
|
private readonly IPlatformRenderInterfaceContext _context;
|
|
private readonly IExternalObjectsRenderInterfaceContextFeature _externalObjects;
|
|
|
|
|
|
public CompositionInterop(
|
|
Compositor compositor,
|
|
IExternalObjectsRenderInterfaceContextFeature externalObjects)
|
|
{
|
|
_compositor = compositor;
|
|
_context = compositor.Server.RenderInterface.Value;
|
|
DeviceLuid = externalObjects.DeviceLuid;
|
|
DeviceUuid = externalObjects.DeviceUuid;
|
|
_externalObjects = externalObjects;
|
|
}
|
|
|
|
public IReadOnlyList<string> SupportedImageHandleTypes => _externalObjects.SupportedImageHandleTypes;
|
|
public IReadOnlyList<string> SupportedSemaphoreTypes => _externalObjects.SupportedSemaphoreTypes;
|
|
|
|
public CompositionGpuImportedImageSynchronizationCapabilities GetSynchronizationCapabilities(string imageHandleType)
|
|
=> _externalObjects.GetSynchronizationCapabilities(imageHandleType);
|
|
|
|
public ICompositionImportedGpuImage ImportImage(IPlatformHandle handle,
|
|
PlatformGraphicsExternalImageProperties properties)
|
|
=> new CompositionImportedGpuImage(_compositor, _context, _externalObjects,
|
|
() => _externalObjects.ImportImage(handle, properties));
|
|
|
|
public ICompositionImportedGpuImage ImportImage(ICompositionImportableSharedGpuContextImage image)
|
|
{
|
|
return new CompositionImportedGpuImage(_compositor, _context, _externalObjects,
|
|
() => _externalObjects.ImportImage(image));
|
|
}
|
|
|
|
public ICompositionImportedGpuSemaphore ImportSemaphore(IPlatformHandle handle)
|
|
=> new CompositionImportedGpuSemaphore(handle, _compositor, _context, _externalObjects);
|
|
|
|
public ICompositionImportedGpuImage ImportSemaphore(ICompositionImportableSharedGpuContextSemaphore image)
|
|
{
|
|
throw new System.NotSupportedException();
|
|
}
|
|
|
|
public bool IsLost { get; }
|
|
public byte[]? DeviceLuid { get; set; }
|
|
public byte[]? DeviceUuid { get; set; }
|
|
}
|
|
|
|
abstract class CompositionGpuImportedObjectBase : ICompositionGpuImportedObject
|
|
{
|
|
protected Compositor Compositor { get; }
|
|
public IPlatformRenderInterfaceContext Context { get; }
|
|
public IExternalObjectsRenderInterfaceContextFeature Feature { get; }
|
|
|
|
public CompositionGpuImportedObjectBase(Compositor compositor,
|
|
IPlatformRenderInterfaceContext context,
|
|
IExternalObjectsRenderInterfaceContextFeature feature)
|
|
{
|
|
Compositor = compositor;
|
|
Context = context;
|
|
Feature = feature;
|
|
|
|
ImportCompeted = Compositor.InvokeServerJobAsync(Import);
|
|
}
|
|
|
|
protected abstract void Import();
|
|
public abstract void Dispose();
|
|
|
|
public Task ImportCompeted { get; }
|
|
public bool IsLost => Context.IsLost;
|
|
|
|
public ValueTask DisposeAsync() => new(Compositor.InvokeServerJobAsync(() =>
|
|
{
|
|
if (ImportCompeted.Status == TaskStatus.RanToCompletion)
|
|
Dispose();
|
|
}));
|
|
}
|
|
|
|
class CompositionImportedGpuImage : CompositionGpuImportedObjectBase, ICompositionImportedGpuImage
|
|
{
|
|
private readonly Func<IPlatformRenderInterfaceImportedImage> _importer;
|
|
private IPlatformRenderInterfaceImportedImage? _image;
|
|
|
|
public CompositionImportedGpuImage(Compositor compositor,
|
|
IPlatformRenderInterfaceContext context,
|
|
IExternalObjectsRenderInterfaceContextFeature feature,
|
|
Func<IPlatformRenderInterfaceImportedImage> importer): base(compositor, context, feature)
|
|
{
|
|
_importer = importer;
|
|
}
|
|
|
|
protected override void Import()
|
|
{
|
|
using (Compositor.Server.RenderInterface.EnsureCurrent())
|
|
{
|
|
// The original context was lost and the new one might have different capabilities
|
|
if (Context != Compositor.Server.RenderInterface.Value)
|
|
throw new PlatformGraphicsContextLostException();
|
|
_image = _importer();
|
|
}
|
|
}
|
|
|
|
public IPlatformRenderInterfaceImportedImage Image =>
|
|
_image ?? throw new ObjectDisposedException(nameof(CompositionImportedGpuImage));
|
|
|
|
public bool IsUsable => _image != null && Compositor.Server.RenderInterface.Value == Context;
|
|
|
|
public override void Dispose()
|
|
{
|
|
_image?.Dispose();
|
|
_image = null!;
|
|
}
|
|
}
|
|
|
|
class CompositionImportedGpuSemaphore : CompositionGpuImportedObjectBase, ICompositionImportedGpuSemaphore
|
|
{
|
|
private readonly IPlatformHandle _handle;
|
|
private IPlatformRenderInterfaceImportedSemaphore? _semaphore;
|
|
|
|
public CompositionImportedGpuSemaphore(IPlatformHandle handle,
|
|
Compositor compositor, IPlatformRenderInterfaceContext context,
|
|
IExternalObjectsRenderInterfaceContextFeature feature) : base(compositor, context, feature)
|
|
{
|
|
_handle = handle;
|
|
}
|
|
|
|
public IPlatformRenderInterfaceImportedSemaphore Semaphore =>
|
|
_semaphore ?? throw new ObjectDisposedException(nameof(CompositionImportedGpuSemaphore));
|
|
|
|
|
|
public bool IsUsable => _semaphore != null && Compositor.Server.RenderInterface.Value == Context;
|
|
|
|
protected override void Import()
|
|
{
|
|
_semaphore = Feature.ImportSemaphore(_handle);
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
_semaphore?.Dispose();
|
|
_semaphore = null;
|
|
}
|
|
}
|
|
|