6.16.0 - A settle gate that can finally see the switch
The display-criteria settle gate has never received a single mode-switch notification. This release fixes that, and the measurements it made possible change how the gate decides when a panel is done.
The observation defect
tvOS posts AVDisplayManagerModeSwitchStart / ...End from an AVSharedDisplayManager, not from the AVDisplayManager that UIWindow.avDisplayManager returns and that preferredDisplayCriteria is written to. The observers filtered on the latter, so every notification was dropped. Device probe listening on all objects (Apple TV 4K 3rd gen, tvOS 26.5):
FIRED AVDisplayManagerModeSwitchStartNotification object=AVSharedDisplayManager@0x10b581a10
our manager=AVDisplayManager@0x1036fdfa0
Six start/end pairs arrived in three playbacks while the engine recorded none. With both notifications invisible, the gate had been deciding on isDisplayModeSwitchInProgress and on the EDR headroom.
What that cost
The headroom peaks during a dynamic-range transition, so using it as the end signal released playback into a running handshake: measured at 2478 ms before the panel finished. The first frame then hit a mid-transition panel, which is precisely what the gate exists to prevent.
Behaviour change
A gate that runs after the item is ready now waits for the end of a switch it observed starting, instead of breaking out after stage2CapMs. Rate-only device round (SDR 25p on a 60 Hz system, no pre-flight): item ready at +443 ms, the old cap released play() at +2130 ms, the panel finished at +3555 ms, and it is dark throughout. Releasing early therefore bought no picture and played 1.4 s of content into a black screen.
Three cases keep the previous 2000 ms cap:
- the pre-flight gate, which runs before the item is built, where breaking out early is what releases the load (AE#348 tracks doing that properly)
- live, so a zap never sits behind a panel handshake
- switches with no recorded start, the unobservable-DV panel, where nothing will report an end and a longer ceiling would be pure startup cost
Because the wait ends on the observed end rather than on a duration, a panel that switches quickly pays only what it takes.
Measurements now in the code
First hardware numbers for a panel handshake, all from an Apple TV 4K (3rd gen) on tvOS 26.5:
| switch | duration |
|---|---|
| dynamic range (12 runs) | 2779 to 2898 ms |
| rate only (2 runs) | ~3550 ms |
The in-progress flag cleared within 1 ms of the end notification, so it is an accurate second signal on that panel. Settle lines now carry the figure directly:
[DisplayCriteria] switch settled via modeSwitchEnd (start pre-gate (start notification, before gate
entry) 0ms before gate entry, total 156ms, switch 2852ms end to end)
StartGrace.brief's sub-second premise is contradicted for dynamic-range and rate switches alike on this hardware; the budgets themselves are unchanged and now carry the numbers in their documentation.
Also fixed
- The mode-switch observation is armed at the criteria write rather than at the play gate, so a switch that starts and finishes during the load is knowable instead of invisible. An end without a start never settles a gate, the in-progress flag may only veto a settle, and a record is evidence only for the load it was armed in.
- Both gates of one load read the same record, so the play gate no longer pays Stage 1's grace to rediscover a switch the pre-flight already watched.
- The entry fast-exit requires the panel to be idle: a panel already in HDR and one mid-transition present the same raised headroom.
Reported via Sodalite#49 and AE#339, with the ordering question that started it now answered by two timestamps rather than by a flag.