mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-01 20:34:57 +01:00
Six levels of detail climbing in even steps, High being where a player with no settings of their own starts. Five parts of the picture can also take a level of their own. Resolutions start from the monitors in the computer. uartfeature with nothing selected writes "no no no no"; uart and uarttune are written whole or not at all. On Linux the file's contents tell a Windows build, a native one and a script from a note that merely has the execute bit.
101 lines
3.7 KiB
C#
101 lines
3.7 KiB
C#
using StarterNG.Infrastructure;
|
|
using StarterNG.Tests.Fakes;
|
|
|
|
namespace StarterNG.Tests;
|
|
|
|
public class DisplaysTests
|
|
{
|
|
/// <summary>A 128-byte block with an 18-byte timing at 54, as a panel's base EDID has it.</summary>
|
|
private static byte[] BaseBlock(int pixelClock10KHz, int hActive, int hBlank, int vActive, int vBlank,
|
|
int extensions = 0)
|
|
{
|
|
var edid = new byte[128];
|
|
new byte[] { 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 }.CopyTo(edid, 0);
|
|
edid[126] = (byte)extensions;
|
|
int at = 54;
|
|
edid[at] = (byte)pixelClock10KHz;
|
|
edid[at + 1] = (byte)(pixelClock10KHz >> 8);
|
|
edid[at + 2] = (byte)hActive;
|
|
edid[at + 3] = (byte)hBlank;
|
|
edid[at + 4] = (byte)((hActive >> 8) << 4 | hBlank >> 8);
|
|
edid[at + 5] = (byte)vActive;
|
|
edid[at + 6] = (byte)vBlank;
|
|
edid[at + 7] = (byte)((vActive >> 8) << 4 | vBlank >> 8);
|
|
return edid;
|
|
}
|
|
|
|
/// <summary>A DisplayID 2.0 block with one type VII timing (kHz, sizes less one).</summary>
|
|
private static byte[] DisplayIdBlock(int pixelClockKHz, int hActive, int hBlank, int vActive, int vBlank)
|
|
{
|
|
var block = new byte[128];
|
|
block[0] = 0x70;
|
|
block[1] = 0x20;
|
|
block[2] = 23; // one data block: 3 bytes of header, 20 of timing
|
|
block[3] = 2;
|
|
int at = 5;
|
|
block[at] = 0x22;
|
|
block[at + 2] = 20;
|
|
int t = at + 3, clock = pixelClockKHz - 1;
|
|
block[t] = (byte)clock;
|
|
block[t + 1] = (byte)(clock >> 8);
|
|
block[t + 2] = (byte)(clock >> 16);
|
|
void Put(int offset, int value)
|
|
{
|
|
block[t + offset] = (byte)(value - 1);
|
|
block[t + offset + 1] = (byte)((value - 1) >> 8);
|
|
}
|
|
Put(4, hActive);
|
|
Put(6, hBlank);
|
|
Put(12, vActive);
|
|
Put(14, vBlank);
|
|
return block;
|
|
}
|
|
|
|
[Fact]
|
|
public void A_plain_monitor_gives_its_preferred_timing()
|
|
{
|
|
// 1920x1080 at 148.5 MHz: the usual 60 Hz.
|
|
Assert.Equal(60, Edid.HighestRefreshRate(BaseBlock(14850, 1920, 280, 1080, 45)));
|
|
}
|
|
|
|
[Fact]
|
|
public void A_fast_panel_found_only_in_displayid_is_read_there()
|
|
{
|
|
// As the eDP panel of a gaming laptop: 60 Hz in the base block, 165 Hz in DisplayID.
|
|
var edid = BaseBlock(15394, 1920, 160, 1200, 35, extensions: 1)
|
|
.Concat(DisplayIdBlock(423250, 1920, 160, 1200, 33)).ToArray();
|
|
|
|
Assert.Equal(165, Edid.HighestRefreshRate(edid));
|
|
}
|
|
|
|
[Fact]
|
|
public void Something_too_short_for_an_edid_has_no_rate()
|
|
{
|
|
Assert.Equal(0, Edid.HighestRefreshRate(new byte[] { 0, 0xFF }));
|
|
Assert.Equal(0, Edid.HighestRefreshRate(new byte[128]));
|
|
}
|
|
|
|
[Fact]
|
|
public void Only_connected_screens_are_listed_by_their_connector()
|
|
{
|
|
var files = new InMemoryFileSystem(caseSensitive: true)
|
|
.WithFile("/sys/class/drm/card1-eDP-1/status", "connected\n")
|
|
.WithFile("/sys/class/drm/card1-HDMI-A-1/status", "disconnected\n")
|
|
.WithFile("/sys/class/drm/card1/device/uevent", "DRIVER=amdgpu\n");
|
|
files.WriteAllBytes("/sys/class/drm/card1-eDP-1/edid", BaseBlock(14850, 1920, 280, 1080, 45));
|
|
files.WriteAllBytes("/sys/class/drm/card1-HDMI-A-1/edid", BaseBlock(14850, 1920, 280, 1080, 45));
|
|
|
|
var displays = new Displays(files, new FakeEnvironment()).List();
|
|
|
|
Assert.Equal(new[] { new Display("eDP-1", 60) }, displays);
|
|
}
|
|
|
|
[Fact]
|
|
public void Off_linux_without_windows_nothing_is_read()
|
|
{
|
|
var environment = new FakeEnvironment { IsLinux = false, IsMacOS = true };
|
|
|
|
Assert.Empty(new Displays(new InMemoryFileSystem(), environment).List());
|
|
}
|
|
}
|