RendererControl.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Data;
  4. using Avalonia.Media;
  5. using Avalonia.Rendering.SceneGraph;
  6. using Ryujinx.Common.Configuration;
  7. using SPB.Windowing;
  8. using System;
  9. namespace Ryujinx.Ava.Ui.Controls
  10. {
  11. internal abstract class RendererControl : Control
  12. {
  13. protected object _image;
  14. static RendererControl()
  15. {
  16. AffectsRender<RendererControl>(ImageProperty);
  17. }
  18. public readonly static StyledProperty<object> ImageProperty =
  19. AvaloniaProperty.Register<RendererControl, object>(
  20. nameof(Image),
  21. 0,
  22. inherits: true,
  23. defaultBindingMode: BindingMode.TwoWay);
  24. protected object Image
  25. {
  26. get => _image;
  27. set => SetAndRaise(ImageProperty, ref _image, value);
  28. }
  29. public event EventHandler<EventArgs> RendererInitialized;
  30. public event EventHandler<Size> SizeChanged;
  31. protected Size RenderSize { get; private set; }
  32. public bool IsStarted { get; private set; }
  33. public GraphicsDebugLevel DebugLevel { get; }
  34. private bool _isInitialized;
  35. protected ICustomDrawOperation DrawOperation { get; private set; }
  36. public RendererControl(GraphicsDebugLevel graphicsDebugLevel)
  37. {
  38. DebugLevel = graphicsDebugLevel;
  39. IObservable<Rect> resizeObservable = this.GetObservable(BoundsProperty);
  40. resizeObservable.Subscribe(Resized);
  41. Focusable = true;
  42. }
  43. protected void Resized(Rect rect)
  44. {
  45. SizeChanged?.Invoke(this, rect.Size);
  46. if (!rect.IsEmpty)
  47. {
  48. RenderSize = rect.Size * VisualRoot.RenderScaling;
  49. DrawOperation?.Dispose();
  50. DrawOperation = CreateDrawOperation();
  51. }
  52. }
  53. protected abstract ICustomDrawOperation CreateDrawOperation();
  54. protected abstract void CreateWindow();
  55. public override void Render(DrawingContext context)
  56. {
  57. if (!_isInitialized)
  58. {
  59. CreateWindow();
  60. OnRendererInitialized();
  61. _isInitialized = true;
  62. }
  63. if (!IsStarted || Image == null)
  64. {
  65. return;
  66. }
  67. if (DrawOperation != null)
  68. {
  69. context.Custom(DrawOperation);
  70. }
  71. base.Render(context);
  72. }
  73. protected void OnRendererInitialized()
  74. {
  75. RendererInitialized?.Invoke(this, EventArgs.Empty);
  76. }
  77. public void QueueRender()
  78. {
  79. Program.RenderTimer.TickNow();
  80. }
  81. internal abstract void Present(object image);
  82. internal void Start()
  83. {
  84. IsStarted = true;
  85. QueueRender();
  86. }
  87. internal void Stop()
  88. {
  89. IsStarted = false;
  90. }
  91. public abstract void DestroyBackgroundContext();
  92. internal abstract void MakeCurrent();
  93. internal abstract void MakeCurrent(SwappableNativeWindowBase window);
  94. }
  95. }