ryujinx/Ryujinx.Ava/Ui/Controls/RendererControl.cs
Emmanuel Hansen c8f9292bab
Avalonia - Couple fixes and improvements to vulkan (#3483)
* drop split devices, rebase

* add fallback to opengl if vulkan is not available

* addressed review

* ensure present image references are incremented and decremented when necessary

* allow changing vsync for vulkan

* fix screenshot on avalonia vulkan

* save favorite when toggled

* improve sync between popups

* use separate devices for each new window

* fix crash when closing window

* addressed review

* don't create the main window with immediate mode

* change skia vk delegate to method

* update vulkan throwonerror

* addressed review
2022-08-16 16:32:37 +00:00

96 lines
2.4 KiB
C#

using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Media;
using Avalonia.Rendering.SceneGraph;
using Ryujinx.Common.Configuration;
using SPB.Windowing;
using System;
namespace Ryujinx.Ava.Ui.Controls
{
internal abstract class RendererControl : Control
{
protected object Image { get; set; }
public event EventHandler<EventArgs> RendererInitialized;
public event EventHandler<Size> SizeChanged;
protected Size RenderSize { get; private set; }
public bool IsStarted { get; private set; }
public GraphicsDebugLevel DebugLevel { get; }
private bool _isInitialized;
protected ICustomDrawOperation DrawOperation { get; private set; }
public RendererControl(GraphicsDebugLevel graphicsDebugLevel)
{
DebugLevel = graphicsDebugLevel;
IObservable<Rect> resizeObservable = this.GetObservable(BoundsProperty);
resizeObservable.Subscribe(Resized);
Focusable = true;
}
protected void Resized(Rect rect)
{
SizeChanged?.Invoke(this, rect.Size);
if (!rect.IsEmpty)
{
RenderSize = rect.Size * VisualRoot.RenderScaling;
DrawOperation = CreateDrawOperation();
}
}
protected abstract ICustomDrawOperation CreateDrawOperation();
protected abstract void CreateWindow();
public override void Render(DrawingContext context)
{
if (!_isInitialized)
{
CreateWindow();
OnRendererInitialized();
_isInitialized = true;
}
if (!IsStarted || Image == null)
{
return;
}
if (DrawOperation != null)
{
context.Custom(DrawOperation);
}
base.Render(context);
}
protected void OnRendererInitialized()
{
RendererInitialized?.Invoke(this, EventArgs.Empty);
}
internal abstract void Present(object image);
internal void Start()
{
IsStarted = true;
}
internal void Stop()
{
IsStarted = false;
}
public abstract void DestroyBackgroundContext();
internal abstract void MakeCurrent();
internal abstract void MakeCurrent(SwappableNativeWindowBase window);
}
}