sharpemu/tests/SharpEmu.Libs.Tests/VideoOut/ShaderCacheProgressOverlayT...

100 lines
4.0 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.Libs.VideoOut;
using SharpEmu.GUI;
using SkiaSharp;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using Xunit;
namespace SharpEmu.Libs.Tests.VideoOut;
public sealed class ShaderCacheProgressOverlayTests
{
static ShaderCacheProgressOverlayTests() => GuiLauncher.ConfigureSplashFont();
[Fact]
public void SplashUsesTheBundledGuiFont()
{
var typeface = (SKTypeface)typeof(ShaderCacheProgressOverlay)
.GetField("_typeface", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null)!;
Assert.Equal("Inter", typeface.FamilyName);
}
[Theory]
[InlineData((int)ShaderCachePhase.Loading)]
[InlineData((int)ShaderCachePhase.Recovering)]
[InlineData((int)ShaderCachePhase.Scanning)]
[InlineData((int)ShaderCachePhase.Preparing)]
[InlineData((int)ShaderCachePhase.Compiling)]
[InlineData((int)ShaderCachePhase.Finalizing)]
public void EveryStageDrawsOverTheSplashWithoutChangingItsSource(int phase)
{
var original = Enumerable.Repeat((byte)120, 640 * 360 * 4).ToArray();
var pixels = original.ToArray();
var snapshot = new ShaderCacheProgressSnapshot(new((ShaderCachePhase)phase, 50, 100),
20, 100, 50, 200, 1, 4, 10, 60, 2, 4, 1, 12);
ShaderCacheProgressOverlay.Draw(pixels, 640, 360, snapshot);
Assert.All(original, value => Assert.Equal(120, value));
Assert.Equal(30, pixels[0]);
Assert.Equal(120, pixels[3]);
Assert.Contains((byte)255, pixels);
}
[Fact]
public void AChangedCounterRepaintsTheProgressBars()
{
var snapshot = new ShaderCacheProgressSnapshot(new(ShaderCachePhase.Compiling),
0, 100, 0, 100, 0, 2, 0, 0, 0, 2, 1, 1);
var first = new byte[640 * 360 * 4];
var next = new byte[first.Length];
ShaderCacheProgressOverlay.Draw(first, 640, 360, snapshot);
ShaderCacheProgressOverlay.Draw(next, 640, 360, snapshot with { ComputeDone = 100, GraphicsDone = 50, Merged = 1 });
Assert.False(first.AsSpan().SequenceEqual(next));
}
[Theory]
[InlineData(1, 1)]
[InlineData(200, 100)]
[InlineData(1920, 1080)]
public void UnknownTotalsAndSmallWindowsAreClippedSafely(int width, int height)
{
var pixels = new byte[width * height * 4];
var snapshot = new ShaderCacheProgressSnapshot(new(ShaderCachePhase.Preparing),
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 42);
ShaderCacheProgressOverlay.Draw(pixels, width, height, snapshot);
}
[Fact]
public void AnIncorrectPixelBufferIsRejected()
{
var snapshot = default(ShaderCacheProgressSnapshot);
Assert.Throws<ArgumentException>(() => ShaderCacheProgressOverlay.Draw(new byte[4], 2, 2, snapshot));
}
[Fact]
public void ProgressRefreshesAnUnchangedSplashAndRequestsOneFinalCleanFrame()
{
var type = typeof(VulkanVideoPresenter).GetNestedType("Presenter", BindingFlags.NonPublic)!;
var presenter = RuntimeHelpers.GetUninitializedObject(type);
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
var progress = type.GetField("_shaderCacheProgress", flags)!;
var visible = type.GetField("_shaderCacheSplashVisible", flags)!;
var lastDraw = type.GetField("_shaderCacheSplashLastDraw", flags)!;
var refresh = type.GetProperty("ShaderCacheSplashNeedsRefresh", flags)!;
progress.SetValue(presenter, new ShaderCacheProgress(ShaderCachePhase.Compiling));
Assert.Equal(true, refresh.GetValue(presenter));
lastDraw.SetValue(presenter, Stopwatch.GetTimestamp() + Stopwatch.Frequency * 60);
Assert.Equal(false, refresh.GetValue(presenter));
progress.SetValue(presenter, null);
visible.SetValue(presenter, true);
Assert.Equal(true, refresh.GetValue(presenter));
visible.SetValue(presenter, false);
Assert.Equal(false, refresh.GetValue(presenter));
}
}