fix(rendering): survive display topology handoff
Model active-monitor refresh telemetry as optional so GLFW display replacement during console/RDP transitions cannot escape the native move callback and terminate the client. Preserve the existing software pacing fallback until a later monitor event succeeds. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
10ccce3f2d
commit
14fbe92b08
4 changed files with 76 additions and 22 deletions
|
|
@ -98,6 +98,37 @@ public sealed class DisplayFramePacingControllerTests
|
|||
Assert.Equal(new FramePacingPolicy(false, 144d), controller.Policy);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unavailable_monitor_during_display_handoff_uses_fallback_policy()
|
||||
{
|
||||
using var profiler = new FrameProfiler();
|
||||
using var controller = new DisplayFramePacingController(
|
||||
uncappedRendering: false,
|
||||
profiler,
|
||||
new FramePacingController(
|
||||
new FakeClock(1_000),
|
||||
new RecordingWaiter()));
|
||||
var surface = new FakeSurface
|
||||
{
|
||||
VSync = false,
|
||||
ActiveMonitorRefreshHz = 144,
|
||||
};
|
||||
controller.InitializeStartup(requestedVSync: false);
|
||||
controller.BindSurface(surface);
|
||||
controller.RefreshActiveMonitor();
|
||||
Assert.Equal(new FramePacingPolicy(false, 144d), controller.Policy);
|
||||
|
||||
surface.MonitorAvailable = false;
|
||||
controller.OnWindowMoved(default);
|
||||
|
||||
Assert.Equal(
|
||||
new FramePacingPolicy(
|
||||
false,
|
||||
FramePacingPolicy.FallbackRefreshHz),
|
||||
controller.Policy);
|
||||
Assert.False(surface.VSync);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Explicit_uncapped_mode_disables_both_pacing_mechanisms()
|
||||
{
|
||||
|
|
@ -172,16 +203,22 @@ public sealed class DisplayFramePacingControllerTests
|
|||
|
||||
public int RefreshReadCount { get; private set; }
|
||||
|
||||
public bool MonitorAvailable { get; set; } = true;
|
||||
|
||||
public int? ActiveMonitorRefreshHz
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshReadCount++;
|
||||
return _activeMonitorRefreshHz;
|
||||
}
|
||||
get => _activeMonitorRefreshHz;
|
||||
set => _activeMonitorRefreshHz = value;
|
||||
}
|
||||
|
||||
public bool TryGetActiveMonitorRefreshHz(out int refreshHz)
|
||||
{
|
||||
RefreshReadCount++;
|
||||
refreshHz = _activeMonitorRefreshHz.GetValueOrDefault();
|
||||
return MonitorAvailable &&
|
||||
_activeMonitorRefreshHz is > 0;
|
||||
}
|
||||
|
||||
public void Dispose() => Disposed = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -789,13 +789,11 @@ public sealed class SilkWindowCallbackBindingTests
|
|||
public bool VSync { get; set; }
|
||||
public int RefreshReadCount { get; private set; }
|
||||
|
||||
public int? ActiveMonitorRefreshHz
|
||||
public bool TryGetActiveMonitorRefreshHz(out int refreshHz)
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshReadCount++;
|
||||
return 144;
|
||||
}
|
||||
RefreshReadCount++;
|
||||
refreshHz = 144;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue