using System.IO; using System.Reactive.Disposables; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Shared; using Avalonia.Media.Imaging; using ReactiveUI; using SkiaSharp; namespace Artemis.UI.Screens.Debugger.Render; public class RenderDebugViewModel : ActivatableViewModelBase { private readonly IRenderService _renderService; private double _currentFps; private Bitmap? _currentFrame; private string? _frameTargetPath; private string? _renderer; private int _renderHeight; private int _renderWidth; public RenderDebugViewModel(IRenderService renderService) { _renderService = renderService; DisplayName = "Rendering"; this.WhenActivated(disposables => { HandleActivation(); Disposable.Create(HandleDeactivation).DisposeWith(disposables); }); } public Bitmap? CurrentFrame { get => _currentFrame; set => RaiseAndSetIfChanged(ref _currentFrame, value); } public double CurrentFps { get => _currentFps; set => RaiseAndSetIfChanged(ref _currentFps, value); } public int RenderWidth { get => _renderWidth; set => RaiseAndSetIfChanged(ref _renderWidth, value); } public int RenderHeight { get => _renderHeight; set => RaiseAndSetIfChanged(ref _renderHeight, value); } public string? Renderer { get => _renderer; set => RaiseAndSetIfChanged(ref _renderer, value); } private void HandleActivation() { Renderer = Constants.ManagedGraphicsContext != null ? Constants.ManagedGraphicsContext.GetType().Name : "Software"; _renderService.FrameRendered += RenderServiceOnFrameRendered; } private void HandleDeactivation() { _renderService.FrameRendered -= RenderServiceOnFrameRendered; } private void RenderServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e) { CurrentFps = _renderService.FrameRate; using SKImage skImage = e.Texture.Surface.Snapshot(); SKImageInfo bitmapInfo = e.Texture.ImageInfo; if (_frameTargetPath != null) { using (SKData data = skImage.Encode(SKEncodedImageFormat.Png, 100)) { using (FileStream stream = File.OpenWrite(_frameTargetPath)) { data.SaveTo(stream); } } _frameTargetPath = null; } RenderHeight = bitmapInfo.Height; RenderWidth = bitmapInfo.Width; // TODO: This performs well enough but look into something else using (SKData data = skImage.Encode(SKEncodedImageFormat.Png, 100)) { CurrentFrame = new Bitmap(data.AsStream()); } } }