123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- 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)
- {
- Surface?.Dispose();
- 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; }
- }
|