Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,38 @@ set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_GAMES OFF CACHE BOOL "" FORCE)
set(CUSTOMIZE_BUILD ON CACHE BOOL "" FORCE)
# raylib 6.0 reads every SUPPORT_ flag in its config.h into an option that defaults to ON, the ones
# config.h defines as 0 included (raysan5/raylib#5844, fixed after 6.0), and CUSTOMIZE_BUILD skips
# config.h's own values. So each of those is on unless it is switched off here.
# SUPPORT_CUSTOM_FRAME_CONTROL was: EndDrawing then never put a frame on the screen, never read
# input and never waited for the next frame, so the Linux window stayed blank, took no keys and
# spun a core. A capture draws into a texture and never gets that far, which is why the pixel
# snapshots passed throughout; PixelTests.PresentWaitsForTheNextFrame is what notices. The busy
# wait loop was on the same way, and would have spun through the whole of every frame's wait once
# there was one. The rest are formats and features nothing here uses.
foreach(flag IN ITEMS
SUPPORT_CUSTOM_FRAME_CONTROL
SUPPORT_BUSY_WAIT_LOOP
SUPPORT_GPU_SKINNING
SUPPORT_FILEFORMAT_TGA
SUPPORT_FILEFORMAT_PSD
SUPPORT_FILEFORMAT_HDR
SUPPORT_FILEFORMAT_PIC
SUPPORT_FILEFORMAT_PNM
SUPPORT_FILEFORMAT_KTX
SUPPORT_FILEFORMAT_ASTC
SUPPORT_FILEFORMAT_PKM
SUPPORT_FILEFORMAT_PVR
SUPPORT_FILEFORMAT_BDF
SUPPORT_FILEFORMAT_FLAC)
set(${flag} OFF CACHE BOOL "" FORCE)
endforeach()
# raylib spins for the last part of every frame by default, for timing precision nothing here
# needs: most of a millisecond of a core per frame, for as long as the viewer is open.
set(SUPPORT_PARTIALBUSY_WAIT_LOOP OFF CACHE BOOL "" FORCE)
# F12 saves a screenshot into the working directory, which is wherever the test run that started
# the viewer was launched from. Unreachable while nothing read input; reachable from here on.
set(SUPPORT_SCREEN_CAPTURE OFF CACHE BOOL "" FORCE)
set(SUPPORT_MODULE_RAUDIO OFF CACHE BOOL "" FORCE)
set(SUPPORT_MODULE_RMODELS OFF CACHE BOOL "" FORCE)
# The formats the viewer compares as pictures and raylib can decode. WebP and ICO are also
Expand Down
Binary file not shown.
Binary file not shown.
29 changes: 29 additions & 0 deletions src/DiffEngineViewer.Tests/PixelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,35 @@ public Task InlineAccepted()
public Task Minimal() =>
Capture(ViewerSession.Apply(Fixtures.File(Fixtures.Long(true), Fixtures.Long(false)), CommandKind.ToggleMinimal));

/// <summary>
/// raylib does three things at the end of a frame, behind one flag: puts it on the screen,
/// reads input, and waits for the next frame. raylib 6.0's CMake turned that flag on, so
/// deview_present did none of them - the window stayed blank and took no keys, and the loop
/// drew as fast as it could. A capture draws into a texture and never gets that far, so every
/// snapshot above kept passing. The wait is the one of the three that can be timed from here,
/// so it stands for all of them. Last in the order, so the frames it draws in the live context
/// come after every capture rather than between two of them.
/// </summary>
[Test]
[PixelTest]
[NotInParallel(nameof(PixelTests), Order = 11)]
[SkipOnMac("A capture host never creates the macOS window, and that head waits for the next frame in its event pump rather than after drawing one.")]
public async Task PresentWaitsForTheNextFrame()
{
var screen = ScreenBuilder.Build(ViewerSession.Resize(Fixtures.File(), columns, rows));
// So the timing starts on a frame boundary
await Assert.That(window!.Present(screen)).IsTrue();

var watch = Stopwatch.StartNew();
for (var frame = 0; frame < 60; frame++)
{
window.Present(screen);
}

// Sixty frames at sixty a second. Unpaced, a bare loop ran at tens of thousands a second.
await Assert.That(watch.Elapsed).IsGreaterThan(TimeSpan.FromMilliseconds(750));
}

static async Task Capture(SessionState state)
{
var screen = ScreenBuilder.Build(ViewerSession.Resize(state, columns, rows));
Expand Down
5 changes: 3 additions & 2 deletions src/DiffEngineViewer.Tests/SkipOnMacAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/// <summary>
/// Skips a test on macOS, with the reason given at the use site.
/// <para>
/// There is one so far and it is specific: what that head shows is drawn by AppKit rather than by
/// the renderer, and <c>deview_capture</c> makes no window for AppKit to draw into.
/// Both uses so far come down to <c>deview_capture</c> making no window on macOS: what that head
/// shows is drawn by AppKit into its window, and it waits for the next frame in that window's
/// event pump.
/// </para>
/// </summary>
public sealed class SkipOnMacAttribute(string reason) : SkipAttribute(reason)
Expand Down
Loading
Loading