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.
140 lines
4.1 KiB
140 lines
4.1 KiB
using System;
|
|
using System.Threading.Tasks;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.LogicalTree;
|
|
using Avalonia.Rendering.Composition;
|
|
using Avalonia.VisualTree;
|
|
|
|
namespace GpuInterop;
|
|
|
|
public abstract class DrawingSurfaceDemoBase : Control, IGpuDemo
|
|
{
|
|
private CompositionSurfaceVisual? _visual;
|
|
private Compositor? _compositor;
|
|
private readonly Action _update;
|
|
private string _info = string.Empty;
|
|
private bool _updateQueued;
|
|
private bool _initialized;
|
|
|
|
protected CompositionDrawingSurface? Surface { get; private set; }
|
|
|
|
public DrawingSurfaceDemoBase()
|
|
{
|
|
_update = UpdateFrame;
|
|
}
|
|
|
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
|
{
|
|
base.OnAttachedToVisualTree(e);
|
|
Initialize();
|
|
}
|
|
|
|
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
|
{
|
|
if (_initialized)
|
|
FreeGraphicsResources();
|
|
_initialized = false;
|
|
base.OnDetachedFromLogicalTree(e);
|
|
}
|
|
|
|
async void Initialize()
|
|
{
|
|
try
|
|
{
|
|
var selfVisual = ElementComposition.GetElementVisual(this)!;
|
|
_compositor = selfVisual.Compositor;
|
|
|
|
Surface = _compositor.CreateDrawingSurface();
|
|
_visual = _compositor.CreateSurfaceVisual();
|
|
_visual.Size = new (Bounds.Width, Bounds.Height);
|
|
_visual.Surface = Surface;
|
|
ElementComposition.SetElementChildVisual(this, _visual);
|
|
var (res, info) = await DoInitialize(_compositor, Surface);
|
|
_info = info;
|
|
if (ParentControl != null)
|
|
ParentControl.Info = info;
|
|
_initialized = res;
|
|
QueueNextFrame();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
if (ParentControl != null)
|
|
ParentControl.Info = e.ToString();
|
|
}
|
|
}
|
|
|
|
void UpdateFrame()
|
|
{
|
|
_updateQueued = false;
|
|
var root = this.GetVisualRoot();
|
|
if (root == null)
|
|
return;
|
|
|
|
_visual!.Size = new (Bounds.Width, Bounds.Height);
|
|
var size = PixelSize.FromSize(Bounds.Size, root.RenderScaling);
|
|
RenderFrame(size);
|
|
if (SupportsDisco && Disco > 0)
|
|
QueueNextFrame();
|
|
}
|
|
|
|
void QueueNextFrame()
|
|
{
|
|
if (_initialized && !_updateQueued && _compositor != null)
|
|
{
|
|
_updateQueued = true;
|
|
_compositor?.RequestCompositionUpdate(_update);
|
|
}
|
|
}
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
{
|
|
if(change.Property == BoundsProperty)
|
|
QueueNextFrame();
|
|
base.OnPropertyChanged(change);
|
|
}
|
|
|
|
async Task<(bool success, string info)> DoInitialize(Compositor compositor,
|
|
CompositionDrawingSurface compositionDrawingSurface)
|
|
{
|
|
var interop = await compositor.TryGetCompositionGpuInterop();
|
|
if (interop == null)
|
|
return (false, "Compositor doesn't support interop for the current backend");
|
|
return InitializeGraphicsResources(compositor, compositionDrawingSurface, interop);
|
|
}
|
|
|
|
protected abstract (bool success, string info) InitializeGraphicsResources(Compositor compositor,
|
|
CompositionDrawingSurface compositionDrawingSurface, ICompositionGpuInterop gpuInterop);
|
|
|
|
protected abstract void FreeGraphicsResources();
|
|
|
|
|
|
protected abstract void RenderFrame(PixelSize pixelSize);
|
|
protected virtual bool SupportsDisco => false;
|
|
|
|
public void Update(GpuDemo? parent, float yaw, float pitch, float roll, float disco)
|
|
{
|
|
ParentControl = parent;
|
|
if (ParentControl != null)
|
|
{
|
|
ParentControl.Info = _info;
|
|
ParentControl.DiscoVisible = true;
|
|
}
|
|
|
|
Yaw = yaw;
|
|
Pitch = pitch;
|
|
Roll = roll;
|
|
Disco = disco;
|
|
QueueNextFrame();
|
|
}
|
|
|
|
public GpuDemo? ParentControl { get; private set; }
|
|
|
|
public float Disco { get; private set; }
|
|
|
|
public float Roll { get; private set; }
|
|
|
|
public float Pitch { get; private set; }
|
|
|
|
public float Yaw { get; private set; }
|
|
}
|
|
|