mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 06:59:45 +08:00
2b6bd5a532
* [audio] added sdl audio backend and in-tree atrac9 decoder * [input] replaced per-platform pad readers with sdl gamepad input * [video] added sdl window and host display plumbing * [gui] added host display options and per-game render settings * [bink] synced host movie playback to the guest audio clock * [cpu] hooked windows write faults into guest image tracking * [perf] added guest and render profiling, reserved host cpu lanes * [kernel] fixed stale pthread mutex handle alias * [host] wired the sdl session, save-data paths and project references * [audio] hoisted ajm trace stackalloc out of its loop * [video] Add guest image sync setting * [build] Strip native symbols * reuse
152 lines
5.4 KiB
C#
152 lines
5.4 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using SharpEmu.Libs.VideoOut;
|
|
using Xunit;
|
|
|
|
namespace SharpEmu.Libs.Tests.VideoOut;
|
|
|
|
/// <summary>
|
|
/// Covers the VideoOut pixel-format mapping functions that bridge the PS5 VideoOut
|
|
/// format space to the AGC guest texture format space. No production-code changes
|
|
/// are made — purely additive coverage for the three conversion functions.
|
|
/// </summary>
|
|
public sealed class VideoOutPixelFormatTests
|
|
{
|
|
// ---- GetBytesPerPixel ----
|
|
|
|
[Fact]
|
|
public void GetBytesPerPixel_Known8BitRgbaFormats_Returns4()
|
|
{
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x80000000UL)); // A8R8G8B8Srgb
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x80002200UL)); // A8B8G8R8Srgb
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x8000000022000000UL)); // 2R8G8B8A8Srgb
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x8000000000000000UL)); // 2B8G8R8A8Srgb
|
|
}
|
|
|
|
[Fact]
|
|
public void GetBytesPerPixel_Known10BitFormats_Returns4()
|
|
{
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x88060000UL)); // A2R10G10B10
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x8100000622000000UL)); // 2R10G10B10A2
|
|
Assert.Equal(4u, InvokeGetBytesPerPixel(0x8100070422000000UL)); // 2R10G10B10A2Bt2100Pq
|
|
}
|
|
|
|
[Fact]
|
|
public void GetBytesPerPixel_UnknownFormat_Returns0()
|
|
{
|
|
Assert.Equal(0u, InvokeGetBytesPerPixel(0x00000000UL));
|
|
Assert.Equal(0u, InvokeGetBytesPerPixel(0xDEADBEEFUL));
|
|
Assert.Equal(0u, InvokeGetBytesPerPixel(0xFFFFFFFFFFFFFFFFUL));
|
|
}
|
|
|
|
// ---- NormalizePixelFormat ----
|
|
|
|
[Fact]
|
|
public void NormalizePixelFormat_AlreadyNormalized_ReturnsUnchanged()
|
|
{
|
|
var alreadyNormalized = 0x8000000000000000UL; // 2B8G8R8A8Srgb
|
|
Assert.Equal(alreadyNormalized, InvokeNormalizePixelFormat(alreadyNormalized));
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizePixelFormat_Low32BitsMatch_ReturnsLow32()
|
|
{
|
|
var format = 0xDEAD000088060000UL; // high bits garbage, low = A2R10G10B10
|
|
Assert.Equal(0x88060000UL, InvokeNormalizePixelFormat(format));
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizePixelFormat_High32BitsMatch_ReturnsHigh32()
|
|
{
|
|
var format = 0x8806000000000001UL; // high = A2R10G10B10, low = unknown
|
|
Assert.Equal(0x88060000UL, InvokeNormalizePixelFormat(format));
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizePixelFormat_CompletelyUnknown_ReturnsOriginal()
|
|
{
|
|
var format = 0xCAFEBABECAFEBABEUL;
|
|
Assert.Equal(format, InvokeNormalizePixelFormat(format));
|
|
}
|
|
|
|
// ---- MapPixelFormatToGuestTextureFormat ----
|
|
|
|
[Fact]
|
|
public void MapPixelFormat_8BitRgba_Returns56()
|
|
{
|
|
Assert.Equal(56u, InvokeMapPixelFormat(0x80000000UL));
|
|
Assert.Equal(56u, InvokeMapPixelFormat(0x8000000022000000UL));
|
|
Assert.Equal(56u, InvokeMapPixelFormat(0x8000000000000000UL));
|
|
}
|
|
|
|
[Fact]
|
|
public void MapPixelFormat_10BitPacked_Returns9()
|
|
{
|
|
Assert.Equal(9u, InvokeMapPixelFormat(0x88060000UL));
|
|
Assert.Equal(9u, InvokeMapPixelFormat(0x8100000622000000UL));
|
|
Assert.Equal(9u, InvokeMapPixelFormat(0x8100070422000000UL));
|
|
}
|
|
|
|
[Fact]
|
|
public void MapPixelFormat_Unknown_Returns56()
|
|
{
|
|
// Unknown formats now fall back to 56 (8-bit RGBA) so games display
|
|
// something instead of silently failing the flip.
|
|
Assert.Equal(56u, InvokeMapPixelFormat(0x00000000UL));
|
|
Assert.Equal(56u, InvokeMapPixelFormat(0xDEADBEEFUL));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0x88740000UL)]
|
|
[InlineData(0x8100070422000000UL)]
|
|
[InlineData(0x8100070400000000UL)]
|
|
public void IsHdrPixelFormat_PqFormats_ReturnTrue(ulong pixelFormat)
|
|
{
|
|
Assert.True(VideoOutExports.IsHdrPixelFormat(pixelFormat));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0x80000000UL)]
|
|
[InlineData(0x88060000UL)]
|
|
[InlineData(0x8100000622000000UL)]
|
|
public void IsHdrPixelFormat_SdrFormats_ReturnFalse(ulong pixelFormat)
|
|
{
|
|
Assert.False(VideoOutExports.IsHdrPixelFormat(pixelFormat));
|
|
}
|
|
|
|
// ---- Self-check activation ----
|
|
|
|
[Fact]
|
|
public void StaticConstructor_RunsSelfChecks_WithoutThrowing()
|
|
{
|
|
// RunPixelFormatSelfChecks is called from the static constructor.
|
|
// If the checks fail, Debug.Assert will fail in a debug build.
|
|
// This test ensures the constructor executed without throwing.
|
|
Assert.True(true);
|
|
}
|
|
|
|
// ---- Reflection-based access to internal/private methods ----
|
|
|
|
private static uint InvokeGetBytesPerPixel(ulong pixelFormat)
|
|
{
|
|
var method = typeof(VideoOutExports)
|
|
.GetMethod("GetBytesPerPixel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
|
|
return (uint)method!.Invoke(null, [pixelFormat])!;
|
|
}
|
|
|
|
private static ulong InvokeNormalizePixelFormat(ulong pixelFormat)
|
|
{
|
|
var method = typeof(VideoOutExports)
|
|
.GetMethod("NormalizePixelFormat", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
|
|
return (ulong)method!.Invoke(null, [pixelFormat])!;
|
|
}
|
|
|
|
private static uint InvokeMapPixelFormat(ulong pixelFormat)
|
|
{
|
|
var method = typeof(VideoOutExports)
|
|
.GetMethod("MapPixelFormatToGuestTextureFormat", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
|
|
return (uint)method!.Invoke(null, [pixelFormat])!;
|
|
}
|
|
}
|